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

时间:2016-08-08 06:02:04

标签: javascript promise filereader chain array-reduce

Javascript, spliced FileReader for large files with Promises, how?演变,它向我展示了Promise如何解析函数,现在我仍然坚持使用相同但在Array.reduce函数内部。

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

然后,我理解答案是http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=es中的某种方式,但我无法理解如何将其应用于此处。我的数组不是promises数组,是一个文件数组。好吧,整件事情仍然让我感到困惑。

这是我的代码,如果我能看到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);
  }
}
  • 经过多次评论后更新,似乎现在可行了......还不确定

    var uploaded_file,start,temp_end,end,content; var BYTES_PER_CHUNK = 100000;

    myArray.reduce(function(previous,current){   返回上一个   .then(function(){     BYTES_PER_CHUNK = 100000;     start = 0;     temp_end = start + BYTES_PER_CHUNK;     end = parseInt(current.size);     if(temp_end&gt; end)temp_end = end;     content ='';     uploaded_file = current;

    upload()
    .then(function(content){
        // do stuff with "content"
        console.log('here')
        return Promise.resolve();
    });
    

    }); },Promise.resolve()) 。然后(函数(){     的console.log( 'EIN'); });

    function upload(){   if(start&lt; end){     返回新的Promise(function(resolve){       var chunk = uploaded_file.slice(start,temp_end);       var reader = new FileReader();       reader.readAsArrayBuffer(块);       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&gt; end)temp_end = end;           决心(上传());         }       }     });   } else {     uploaded_file = null;     return Promise.resolve(content);   } }

  • 改进代码,似乎有用,也许更容易阅读?

        var start, temp_end, end;
        var BYTES_PER_CHUNK = 100000;
    
        myArray.reduce(function(previous, current) {
            return previous
            .then(function() {
                start = 0;
                temp_end = start + BYTES_PER_CHUNK;
                end = parseInt(current.size);
                if (temp_end > end) temp_end = end;
                current.data = '';
    
                return upload(current)
                .then(function(){
                    // do other stuff
                    return Promise.resolve();
                });
            });
        },Promise.resolve())
        .then(function(){
          // do other stuff
        });
    
        function upload(current) {
            if (start < end) {
                return new Promise(function(resolve){
                    var chunk = current.slice(start, temp_end);
                    var reader = new FileReader();
                    reader.readAsText(chunk);
                    reader.onload = function(e) {
                        if (e.target.readyState == 2) {
                            current.data += e.target.result;
                            start = temp_end;
                            temp_end = start + BYTES_PER_CHUNK;
                            if (temp_end > end) temp_end = end;
                            resolve(upload(current));
                        }
                    }
                });
            } else {
                return Promise.resolve();
            }
        }
    

1 个答案:

答案 0 :(得分:3)

你非常接近!您需要使用之前的值;它应该是一个承诺。将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);
    };
}

然后你的减少只是:

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

但是upload_file变量有一个很大的错误。该变量是reduce函数范围的本地变量,因此它undefined位于upload内。将其作为参数传递:

function upload(upload_file) { ... }

关于var的附注。这就是为什么即使你在reduce函数中设置upload_file var,也就是为upload调用该函数之前的任何东西:

&#13;
&#13;
var a = 3;

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

foo();
console.log(a); // 3
&#13;
&#13;
&#13;