Node.js多await方法未按顺序串行执行,Sharp处理图片图层绘制顺序错乱
问题根因
绘制顺序错乱的核心原因是异步方法未按顺序等待执行:
drawLayer是异步函数,但你在layers.forEach遍历中直接调用时没有加await,外层draw函数也不是异步函数,导致所有图层的处理任务并发执行- 不同图层的sharp转buffer、图片加载耗时不同,哪个任务先执行完成就会先绘制到画布上,完全无法遵循layers数组的预设顺序
- 你之前直接调用
loadImage(path)没出问题只是巧合,单步异步耗时短,恰好按照调用顺序完成了而已,本质也存在顺序错乱的风险
修复方案
第一步:调整draw函数的异步执行逻辑
将draw改为异步函数,用for of循环替代forEach(forEach不支持await阻塞),按顺序等待每个图层绘制完成后再处理下一个图层、下一个版本:
async function draw() { for (let i = 1; i <= edition; i++) { // 按图层顺序逐个等待绘制完成 for (const layer of layers) { await drawLayer(layer, i); } addMetadata(i); console.log("Creating edition " + i); // 可选:如果每个edition需要独立画布,这里加清空画布逻辑 // ctx.clearRect(0, 0, canvas.width, canvas.height); } } // 调用draw的地方需要加await或者用then接收回调 draw().then(() => { console.log("所有版本生成完成"); });
调整后即可保证图层严格按照layers数组的顺序绘制,和你之前不加sharp处理的逻辑表现完全一致。
第二步:Sharp Buffer转drawImage可用对象的替代方案
你目前用loadImage(buffer)的写法本身是正确的,如果你用的是node-canvas库,还有更直接的写法,不需要额外引入loadImage依赖:
// 先从canvas库引入Image构造函数 const { createCanvas, Image } = require('canvas'); // 在drawLayer中替换图片加载逻辑即可 const buffer = await sharp(`${_layer.location}${element.fileName}`).png().toBuffer(); const image = new Image(); image.src = buffer; // 直接传入drawImage使用 ctx.drawImage( image, _layer.position.x, _layer.position.y, _layer.size.width, _layer.size.height );
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

