如何同步调用异步JavaScript函数?

时间:2018-05-24 20:53:43

标签: javascript javascript-events upload

过去两天我一直在处理这个问题,我的头脑即将爆炸。

我在SO中检查了与我的问题相关的每个问题,但找不到解决方法。

我想做的是;用户尝试上传图像,在客户端调整大小,然后上传。我用过Pica library。一个文件的一切正常。但是,当我将其更改为多个文件时,我会得到最后一个图像的副本。

发生了什么:循环1到N次 - > resizeImg N次

理想解决方案:循环1 - > resizeImg(1) - >循环2 - > resizeImg(2)

任何帮助将不胜感激。

我的代码在

下面
function resizeImg(source) {
    img = new Image;
    img.src = source;
    img.onload = function() {
        width = img.naturalWidth;
        height = img.naturalHeight;
        ratio = Math.min(targetWidth / width, targetHeight / height);
        resizer = window.pica();
        canvas = document.createElement("canvas");
        ctx = canvas.getContext("2d");
        ctx.canvas.width = width * ratio;
        ctx.canvas.height = height * ratio;
        resizer.resize(img, canvas, {
            quality: 3,
            alpha: true,
            unsharpAmount: 0
        }).then(result => resizer.toBlob(result, 'image/jpeg', 0.90)).then(blob => imgBlobArray.push(blob)).then(function() {
            console.log(i);
            console.log(imgBlobArray);
        });
    };
}
document.getElementById('select').onchange = function(evt) {
    for (i = 0; i < this.files.length; i++) {
        resizeImg(window.URL.createObjectURL(this.files[i]));
    }
}

2 个答案:

答案 0 :(得分:2)

问题是,对于img的每次调用,您都没有resizeImg的单独绑定 - 您没有varconst或{{ 1}}在第一次使用let之前。您隐式创建了一个全局变量。所以,对于解释器来说,它看起来像

img

var img; function resizeImg(source) { img = new Image; img.src = source; img.onload = function() { 正在不断重新分配。因此,在所有迭代之后,img最终只会 使用img创建的最后一个img - 对其他resizeImg的引用失去了。

因此,请始终明确声明变量,以确保Image的每次调用都具有单独的resizeImg绑定。对所有其他变量也一样,或者它们将是隐式全局的。

img

答案 1 :(得分:0)

您可以尝试定义像这样的递归函数

function resizeImgRec(files, i) {
    if (i >= files.length)
        return;

    ...

    img.onload = function() {
        ...
        resizer.resize(img, canvas, {
            ...
        }).then(result => resizer.toBlob(result, 'image/jpeg', 0.90)).then(blob => imgBlobArray.push(blob)).then(function() {
            console.log(i);
            console.log(imgBlobArray);
            resizeImg(files, i + 1);
        });
    };
}

document.getElementById('select').onchange = function(evt) {
    resizeImgRec(this.files, 0);
}

这样下一个resizeImg只会在最后一个承诺解决后执行。