如何等到所有的承诺完成

How to wait until all the promises finish

假设,我们想在上传图片之前检查图片的宽度。 Here is the fiddle。最后我们需要等待所有的异步操作结束。为此,我尝试使用 Promises。但是,不幸的是,good_images 里面的 alert 是空的。看来,我错过了一些简单的东西。

我试过Promise.all,但还是不行。 Fiddle.

$(document).ready(function () {
    function check_image_dimensions ($this, image, img_name) {

        let min_width = + $this.data('min_width');
        if (typeof(min_width) === "number" && image.width < min_width) {
            alert(`Error loading photo ${img_name}, image width: ${image.width}px is less then minimal: ${min_width}px.`);
            return false;
        }

        return true;
    }

    function unknown_error () {
        alert('Unknown error while loading image.');
    }

    $(document).on('change', '.upload_images', function() {
        var $this = $(this);
        let images = $this.prop('files');
        if (typeof(images) === 'undefined' || images.length === 0) {
            return false;
        }

        let good_images = Array();
        let promise = Promise.resolve();// <- I tried this, but it is wrong
        for (let i = 0; i < images.length; i++) {
            let promise = new Promise(function(resolve, reject) {
                const reader = new FileReader();
                reader.onload = resolve;
                reader.readAsDataURL(images[i]);
            });

            promise.then((event) => {
                const img  = new Image();
                img.onload = () => {
                    if(check_image_dimensions($this, img, images[i].name) === true) {
                        good_images.push(i);
                    }
                };

                img.onerror = unknown_error;
                img.src = event.target.result;
                return i;
            }).catch(unknown_error);
        }

        promise.then(() => alert(good_images));
    });
});

问题是您只是调用“then”而没有再次设置变量。请参阅以下示例。

let arrdata = [1,2,3,4];
let prom = Promise.resolve();

arrdata.map(data => {

  // Here's the deal
  prom = prom.then(() => {
    console.log(data);
  });
});

prom.then(() => console.log('end'));

如果您想并行处理所有这些图像,您可以创建一个承诺数组并使用 Promise.all 等待它们。请注意,在处理您的图像时,您还需要将该部分包装在一个承诺中:

const good_images = [];
const promises = [];
for (let i = 0; i < images.length; I++) {
  const image = images[I];
  let promise = new Promise( ... );

  promise = promise.then((event) => {
    const img = new Image();
    img.src = event.target.result;

    return new Promise(resolve => {
      img.onload = () => {
        if (is_good(img)) {
          good_images.push(i);
        }
        resolve();
      };
    });
  })

  promise = promise.catch(() => { ... });

  promises.push(promise);
});

Promise.all(promises).then(() => alert(good_images));