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); } }
调整说明
- 替换
forEach为for...of循环后,每次循环都会等待当前帧的所有异步操作执行完成,再处理下一个帧 - 统一使用
await语法替代混用await + then的写法,避免嵌套逻辑混乱 - 给最终写入操作添加
await,避免文件写入未完成就提前结束函数
内容的提问来源于stack exchange,提问作者Stephen Fong
相关产品推荐
相关产品推荐

