如何在 javascript 中使用 promise 获取多个图像文件信息

How to get multiple image file infos using promise in javascript

我正在使用 promise 获取多个上传图像文件的尺寸。 这是我尝试过的方法,但我得到的是空数组。

<input type="file" multiple>

Javascript 文件

$('input').change(function() {

    var filereaders = [];
    var dimensions = [];
      for (var i = 0; i < this.files.length; ++i) {
        filereaders[i] = new FileReader;
        filereaders[i].onload = function() {
          var img = new Image;

          dimensions[i] = new Promise(function (resolve, reject) {
            img.onload = function() {
                    resolve(img.width)
            };
          })      
          img.src = this.result;
        } 

        filereaders[i].readAsDataURL(this.files[i]);
      }

      Promise.all(filereaders).then(function(res){
          Promise.all(dimensions).then(function(dims){
            console.log(dims) // [] array,I expect [23,434,123]...
          }).catch(function(errdims){
            console.log(errdims)
          })
      }).catch(function(err){
        console.log(err)
      })
});
Promise.all(filereaders)

filereaders 是一个 FileReader 实例数组,而不是一个 Promises 数组。在此数组上调用 Promise.all 将立即解析 Promise, 任何 fileReader.onload 事件处理程序触发之前。因此,此时 dimensions 数组仍然是空的。现在我们到达 Promise.all(dimensions),它是一个空数组。

对于您的第一个 Promise.all 调用,您可以将 FileReader 包装在 Promises 中并解析它们 onload:

var filereaders = []
for (var i = 0; i < this.files.length; ++i) {
  var file = this.files[i]
  filereaders.push(new Promise(function (resolve, reject) {
    var fileReader = new FileReader;
    fileReader.onload = function() {
      var img = new Image;

      dimensions[i] = new Promise(function (resolve, reject) {
        img.onload = function() {
          resolve(img.width)
        };
      })      
      img.src = this.result;

      resolve();
    } 

    fileReader.readAsDataURL(file);
  }))
}

现在,filereaders 是一个 Promise 数组,因此您可以在其上使用 Promise.all

不过,还可以做一些其他事情来简化此代码。 File JavaScript 中的对象是 Blob,并且 Blobs can be added as Image .srcs without first reading them with a FileReader. Use URL.createObjectURL:

var dimensions = [];
for (var i = 0; i < this.files.length; ++i) {
  var file = this.files[i];
  dimensions.push(new Promise(function (resolve, reject) {
    var src = URL.createObjectURL(file);
    var img = new Image;
    img.onload = function () {
      resolve(img.width);
      URL.revokeObjectURL(src);
    };
    img.src = src;
  }));
}

现在只需要等待Promise.all(dimensions),就可以完全忘记filereaders

Promise.all(dimensions).then(function(dims){
  console.log(dims) // [] array,I expect [23,434,123]...
}).catch(function(errdims){
  console.log(errdims)
})