【问题标题】:Javascript, spliced FileReader for large files with Promises, how?Javascript,用 Promises 拼接大文件的 FileReader,怎么样?
【发布时间】:2016-08-07 14:29:16
【问题描述】:

我正在尝试使用 FileReader 使用 Promise 顺序读取多个文件。问题是我需要将读取操作分成几块以使其可行。这样一来,我就失去了 Promise 链。这就是在以下代码中发生的情况,我得到控制台日志here,然后是catched(意味着我丢失了链),然后是inside,然后是finished。不知何故,上传中的承诺没有得到尊重。

这是代码(请转到最后的编辑,我保留原文)

var reader = new FileReader();
reader.onloadend = function(e) {
  if (e.target.readyState == 2) {
    console.log('inside')
    start = temp_end;
    temp_end = start + BYTES_PER_CHUNK;
    if (temp_end > end) temp_end = end;
    upload();
  }
};

Array.reduce(function(promise, item) {
  start = 0;
  temp_end = start + BYTES_PER_CHUNK;
  end = parseInt(totalsize);
  if (temp_end > end) temp_end = end;
  uploading_file = item;
  return upload()
  .then(function(){
    console.log('not shown');
  })
  .catch(console.log('catched'));
},0);

function upload() {
  return new Promise(function(resolve,reject) {
    if (start < end) {
      console.log('here')
      var chunk = uploading_file.slice(start, temp_end);
      reader.readAsBinaryString(chunk);
    } else {
      console.log('finished')
      uploading_file = null;
      resolve();
    }
  }
}

EDIT1:我正在尝试的新代码,console.log stop 1 仍然出现在 uploadhere 2 之前

        var start = 0;
        var temp_end = start + BYTES_PER_CHUNK;
        var end = parseInt(item.size);
        if (temp_end > end) temp_end = end;
        uploading_file = item;
        console.log('here 1')
        Promise.resolve().then(function() {
            return upload();
        })
        .then(function(){
            console.log('here 2')
        })
        .catch(console.log('stop 1'));

        function upload() {
            console.log('upload')
            if (start < end) {
                var chunk = uploading_file.slice(start, temp_end);
                var reader = new FileReader();
                reader.readAsArrayBuffer(chunk);
                reader.onload = function(e) {
                    if (e.target.readyState == 2) {
                        start = temp_end;
                        temp_end = start + BYTES_PER_CHUNK;
                        if (temp_end > end) temp_end = end;
                        return upload();
                    }
                }
            } else {
                console.log('finished')
                uploading_file = null;
                return Promise.resolve();
            }
         }

EDIT2:由于缺少函数(),捕获日志在那里。下面的代码似乎可以工作,但最后我看不到我感兴趣的值content

console.log 显示,promise 确实在这里不起作用

here 1
here 2
here 4
here 3

代码:

        var item; // item is a file
        var BYTES_PER_CHUNK = 100000;
        var start = 0;
        var temp_end = start + BYTES_PER_CHUNK;
        var end = parseInt(item.size);
        if (temp_end > end) temp_end = end;
        var content = ''; // to be filled by the content of the file
        var uploading_file = item;
console.log('here 1');
        Promise.resolve().then(function() {
console.log('here 2');
            return upload();
        })
        .then(function(content){
console.log('here 4');
            console.log(content); // this is empty (!!)
        })
        .catch(function(){
            console.log('stop 1')
        });

        function upload() {
            if (start < end) {
                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;
                        return upload();
                    }
                }
            } else {
                uploading_file = null;
                console.log(content); // it shows the content of the file
console.log('here 3');
                return Promise.resolve(content);
            }
        }

【问题讨论】:

  • 我发现很难理解你想要做什么。您有很多未声明的变量、共享状态和不正确的代码(Array.reduceArray 实际上是您真实代码中的变量吗?)。而upload 似乎与上传无关,并且返回的承诺有时不会解决或拒绝。我将尝试猜测尝试,但如果您能准确说明代码的目的是什么。
  • 请到最后的EDIT获取最终代码。无论如何,Array.reduce 意味着我有一个数组并且我使用了 reduce,但这部分代码对于我想要隔离的问题确实并不重要。我希望最后的代码更清楚我想要实现的目标?最终目标是按块读取文件,并通过 Promise 保持对它的控制
  • 现在清楚多了,谢谢。
  • @GWorking 行得通,看来这家伙需要像你的stackoverflow.com/questions/57206375/multifile-upload-as-chunks 一样的解决方案@
  • @Jayavel 我已经删除了这个问题的链接,自从... 2 年前我就一直没有处理文件上传,这里有点生疏:)

标签: javascript promise filereader chain


【解决方案1】:

您的 upload() 函数并不总是返回 Promise。它在 else 条件下有效,但在 if 条件下则不然。您有一个 return 语句,但它在 callback 内部,因此upload 的调用者不会收到它。

尝试将其更改为:

function upload() {
  if (start < end) {
    return new Promise(function (resolve, reject) {
      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;
    console.log(content); // it shows the content of the file
    return Promise.resolve(content);
  }
}

现在,upload 总是返回 Promise 而不是 undefined

【讨论】:

  • 太棒了。就是这个。千恩万谢!我现在在这里使用 Array.reduce 很麻烦。既然这已经很好地解决了,我要为此提出一个新问题,stackoverflow.com/questions/38822187/…,以防你有时间
猜你喜欢
  • 1970-01-01
  • 2014-11-06
  • 2010-12-24
  • 2016-10-02
  • 1970-01-01
  • 2023-03-10
  • 2017-10-09
  • 2011-05-14
  • 2017-12-14
相关资源
最近更新 更多