You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript/TypeScript循环内await不生效:Jimp.loadFont未阻塞执行

问题根因

Array.prototype.forEach 原生不支持异步等待,传入的 async 回调返回的 Promise 会被直接忽略,不会被外层的 await 捕获,因此所有帧的处理逻辑会并发执行,还没等字体加载、帧处理完成,就会执行到最后的 GifUtil.write 逻辑,自然会出现非预期输出甚至崩溃。

修复代码

export class GifWriter {
    async writeTextOnGif(options: GifWriterOptions) {
        let src = this.getSrc(options.src);
        let dest = options.dest;
    
        var frames: GifFrame[] = [];
    
        // 替换await+then混用写法,逻辑更清晰
        const inputGif = await GifUtil.read(src);
        console.log(inputGif.frames.length);
        console.log(options.text_options.length);

        // 把forEach替换为支持异步等待的for...of循环
        for (const frame of inputGif.frames) {
            var jimpCopied = GifUtil.copyAsJimp(Jimp, frame);

            for (var index = 0; index < options.text_options.length; index++) {
                console.log(`index ${index} start`);

                let text = options.text_options[index].text;
                let font = this.getFont(options.text_options[index].font_path, options.text_options[index].font_color, options.text_options[index].font_size);
                let alignmentX = this.getAlignmentX(options.text_options[index].alignmentX);
                let alignmentY = this.getAlignmentY(options.text_options[index].alignmentY);
                let positionX = options.text_options[index].positionX;
                let positionY = options.text_options[index].positionY;
                let [offsetX, offsetY, maxWidth, maxHeight] = this.getPosition(jimpCopied, positionX, positionY);

                console.log(`index ${index} about to loadFont ${font}`);
                console.log(`index ${index} loadFont start`);
                // 直接用await等待字体加载完成
                const loadedFont = await Jimp.loadFont(font);
                jimpCopied.print(loadedFont, offsetX, offsetY, {
                    text: text,
                    alignmentX: alignmentX,
                    alignmentY: alignmentY
                    },
                    maxWidth,
                    maxHeight);
                console.log(`index ${index} loadFont end`);
                console.log(`index ${index} end`);
            }
            console.log(`create GifFrame`);
            const GifCopied = new GifFrame(jimpCopied.bitmap,{
                disposalMethod: frame.disposalMethod,
                delayCentisecs: frame.delayCentisecs,
            });
            GifUtil.quantizeSorokin(GifCopied, 256);
            frames.push(GifCopied); 
        }

        // 写入操作也加await,保证写入完成再结束函数
        await GifUtil.write(dest, frames);
    }
}

调整说明

  1. 替换 forEach 为 for...of 循环后,每次循环都会等待当前帧的所有异步操作执行完成,再处理下一个帧
  2. 统一使用 await 语法替代混用 await + then 的写法,避免嵌套逻辑混乱
  3. 给最终写入操作添加 await,避免文件写入未完成就提前结束函数

内容的提问来源于stack exchange,提问作者Stephen Fong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:15:07