Javascript,使用 Promises 在 Array.reduce 中上传多个文件,怎么样?

Javascript, uploading several files within an Array.reduce with Promises, how?

演变而来,它向我展示了 Promise 如何也可以解析一个函数,现在我坚持使用相同的方法,但在 Array.reduce 函数中。

我的目标是我想在一个数组中上传一个文件(已经上传),其中每个数组项(一个文件)都是按顺序上传的(即通过承诺控制)。

然后,我知道答案不知何故在 http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=es 中,但我不明白如何将其应用到这里。我的数组不是承诺数组,而是文件数组。好吧,整件事对我来说仍然很模糊。

这是我的代码,如果我能看到 ein console.log 消息,它就可以工作:

return myArray.reduce(function(previous, current) {
    var BYTES_PER_CHUNK = 100000;
    var start = 0;
    var temp_end = start + BYTES_PER_CHUNK;
    var end = parseInt(current.size);
    if (temp_end > end) temp_end = end;
    var content = ''; // to be filled by the content of the file
    var uploading_file = current;
    Promise.resolve().then(function() {
        return upload();
    })
    .then(function(content){
        // do stuff with the content
        Promise.resolve();
    });
},0)  // I add the 0 in case myArray has only 1 item
//},Promise.resolve()) goes here?

.then(function(){
    console.log('ein') // this I never see
});

function upload() {
  if (start < end) {
    return new Promise(function(resolve){
      var chunk = uploading_file.slice(start, temp_end);
      var reader = new FileReader();
      reader.readAsArrayBuffer(chunk);
      reader.onload = function(e) {
        if (e.target.readyState == 2) {
          content += new TextDecoder("utf-8").decode(e.target.result);
          start = temp_end;
          temp_end = start + BYTES_PER_CHUNK;
          if (temp_end > end) temp_end = end;
          resolve(upload());
        }
      }
    });
  } else {
    uploading_file = null;
    return Promise.resolve(content);
  }
}

你非常接近!您需要使用之前的值;这应该是一个承诺。将 reduce 的初始值设置为 Promise.resolve()。然后在 reduce 函数内部,而不是 Promise.resolve().then(...)。你应该有这样的东西:

return previous
  .then(function() { return upload(current); })
  .then(function() { /* do stuff */ });

重要的是你 return 在这里。这将在下次调用 reduce 函数时变为 previous


upload 函数有很多问题。 最大的问题是你传递变量的方式使得它很难阅读:)(而且容易出错!)

如果您只是阅读文本文件,请改用 readAsText。请注意,我已将其重命名为 readFile,因为这是一个更准确的名称。

// returns a promise with the file contents
function readFile(file) {
    return new Promise(function (resolve) {
        var reader = new FileReader();
        reader.onload = function(e) {
            resolve(e.target.result);
        };
        reader.readAsText(file);
    };
}

那么你的 reduce 就是:

files.reduce(function(previous, file) {
    return previous
      .then(function() { return readFile(file); })
      .then(function(contents) {
          // do stuff
      });
}, Promise.resolve());

但是 upload_file 变量有一个大错误。该变量在 reduce 函数的范围内是局部的,因此它会在 uploadundefined。而是将其作为参数传递:

function upload(upload_file) { ... }

var 旁注。这就是为什么即使您在 reduce 函数中将 upload_file 设置为 var,它也会是为 upload:

调用该函数之前的任何内容

var a = 3;

function foo() {
  var a = 4;
  console.log(a); // 4
}

foo();
console.log(a); // 3