首页 文章

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

提问于
浏览
0

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){return previous .then(function(){BYTES_PER_CHUNK = 100000; start = 0; temp_end = start BYTES_PER_CHUNK; end = parseInt(current.size); if(temp_end> end)temp_end = end; content =''; uploaded_file = current;

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

}); },Promise.resolve()) . then(function(){console.log('ein');});

function upload(){if(start <end){return new Promise(function(resolve){var chunk = uploaded_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 {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 回答

  • 3

    你非常接近!你需要 use 之前的值;它应该是一个承诺 . 将reduce的初始值设置为 Promise.resolve() . 然后在reduce函数里面,而不是 Promise.resolve().then(...) . 你应该有类似的东西:

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

    你这里很重要 return . 下次调用reduce函数时,这将变为 previous .


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

    如果您只是阅读文本文件,请改用 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函数范围的本地变量,因此它将在 uploadundefined . 将其作为参数传递:

    function upload(upload_file) { ... }
    

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

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

相关问题