在画布上绘制时的javascript promis/async/await行为

在画布上绘制时的javascript promis/async/await行为,javascript,asynchronous,canvas,async-await,promise,Javascript,Asynchronous,Canvas,Async Await,Promise,这是我的问题: 我有一类由一定数量的属性和方法定义的对象,其中: 恢复为文本或图像的“类型”属性 一种drawObject方法,如果对象是图像,则在画布上绘制(画布drawImage函数),如果对象是文本,则在同一画布上“写入”对象(画布fillText函数) 在画布上,我可以绘制/写入存储在数组中的任意数量的对象 我的问题是,我试图以给定的顺序绘制这些对象,以便重叠与数组中对象的顺序一致 为此,我将以以下方式解析数组中的所有对象: function drawer(obj) { re

这是我的问题: 我有一类由一定数量的属性和方法定义的对象,其中:

  • 恢复为文本或图像的“类型”属性
  • 一种drawObject方法,如果对象是图像,则在画布上绘制(画布drawImage函数),如果对象是文本,则在同一画布上“写入”对象(画布fillText函数)
在画布上,我可以绘制/写入存储在数组中的任意数量的对象

我的问题是,我试图以给定的顺序绘制这些对象,以便重叠与数组中对象的顺序一致

为此,我将以以下方式解析数组中的所有对象:

function drawer(obj) {
    return new Promise((resolve) => {
            let objToDraw = obj.drawObject();
            resolve(objToDraw);
    })
}

async function drawObjects() {
    for (const obj of pageObjects) {
        await drawer(obj);
    }
}

drawObjects();
我的期望是,如果drawObject函数完成了它的工作,包括画布上的绘图,那么“for of”循环只会从一个迭代转到下一个迭代。 但所有“文本”对象总是在图像之前绘制,甚至图像有时也会以意外的顺序绘制

以下是drawObject、wrapText(由drawObject调用)方法:

drawObject() {
        if (this.type == "image")
        {
            var drawTheImg = new Image();
            drawTheImg.src = this.destImg
            drawTheImg.onload = function () {
                showCtx.save();
                showCtx.drawImage(drawTheImg, this.sx, this.sy, swidth, sheight, this.dx, this.dy, this.dwidth, this.dheight);
                showAlbumCtx.restore();
}.bind(this)
        } else {
            showAlbumCtx.save();
            showAlbumCtx.fillStyle = this.fontColor;
            showAlbumCtx.textBaseline = "top";
            this.wrapText((this.dy + this.textLineHeight));
            showAlbumCtx.restore();
        }
    }

    wrapText(y) {
        var words = this.containedText.split(' ');
        var line = '';
        showAlbumCtx.save();

        if (this.txtJustification === "right") {
            var x = (this.dx + this.textPadding) + (this.dwidth - this.textPadding);
        } else if (this.txtJustification === "center") {
            var x = (this.dx + this.textPadding) + ((this.dwidth - this.textPadding) / 2);
        } else {
            x = (this.dx + this.textPadding);
        }

        for(var n = 0; n < words.length; n++) {
            var testLine = line + words[n] + ' ';
            var metrics = showAlbumCtx.measureText(testLine);
            var testWidth = metrics.width;
            if (n > 0 && words[n - 1].match(/\n/g)) {
                showAlbumCtx.fillText(line, x, y);
                line = words[n] + ' ';
                y += this.textLineHeight;
            } else if (testWidth > this.textMaxWidth && n > 0) {
                showAlbumCtx.fillText(line, x, y);
                line = words[n] + ' ';
                y += this.textLineHeight;
            } else {
                line = testLine;
            }
        }

        showAlbumCtx.fillText(line, x, y);
        showAlbumCtx.restore();
    }
drawObject(){
if(this.type==“image”)
{
var drawTheImg=新图像();
drawTheImg.src=this.desting
drawTheImg.onload=函数(){
showCtx.save();
showCtx.drawImage(drawTheImg、this.sx、this.sy、swidth、sheight、this.dx、this.dy、this.dwidth、this.dheight);
showAlbumCtx.restore();
}.绑定(此)
}否则{
showAlbumCtx.save();
showAlbumCtx.fillStyle=this.fontColor;
showAlbumCtx.textBaseline=“top”;
this.wrapText((this.dy+this.textLineHeight));
showAlbumCtx.restore();
}
}
wrapText(y){
var words=this.containedText.split(“”);
var行=“”;
showAlbumCtx.save();
如果(this.txtjustization==“right”){
var x=(this.dx+this.textpacking)+(this.dwidth-this.textpacking);
}else if(this.txtjustization==“center”){
var x=(this.dx+this.textpacking)+(this.dwidth-this.textpacking)/2);
}否则{
x=(this.dx+this.textPadding);
}
for(var n=0;n0&&words[n-1]。匹配(/\n/g)){
showAlbumCtx.fillText(行,x,y);
行=字[n]+'';
y+=此.textLineHeight;
}else if(testWidth>this.textMaxWidth&&n>0){
showAlbumCtx.fillText(行,x,y);
行=字[n]+'';
y+=此.textLineHeight;
}否则{
直线=测试线;
}
}
showAlbumCtx.fillText(行,x,y);
showAlbumCtx.restore();
}

感谢您提供的任何建议

以防任何人需要答案。在我的案例中,通过使用Bergi的建议并使drawObject返回承诺,问题已得到解决。

您的
drawObject
方法需要返回承诺(在加载和绘制图像时解决)。仅在
新承诺
中调用
drawObject
并不能消除它-您可以立即使用返回值
undefined
解析承诺。这可能很有用:但实际上最好的方法是首先加载资产,然后开始绘制。当您已经开始绘图时,必须等待资源,这意味着“未完成”的绘图可能是可见的。