FileReader()的Javascript承诺

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (79)

我有以下HTML代码:

<input type='file' multiple>

这是我的JS代码:

var inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = function(){
    var fr = new FileReader();
    for(var i = 0; i < inputFiles.files.length; i++){
        fr.onload = function(){
            console.log(i) // Prints "0, 3, 2, 1" in case of 4 chosen files
        }
    }
    fr.readAsDataURL(inputFiles.files[i]);
}

所以我的问题是,如何使这个循环同步?首先等待文件完成加载然后转到下一个文件。有人告诉我使用JS Promises。但我不能让它发挥作用。这是我正在尝试的:

var inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = function(){
    for(var i = 0; i < inputFiles.files.length; i++){
        var fr = new FileReader();
        var test = new Promise(function(resolve, reject){
            console.log(i) // Prints 0, 1, 2, 3 just as expected
            resolve(fr.readAsDataURL(inputFiles.files[i]));
        });
        test.then(function(){
            fr.onload = function(){
                console.log(i); // Prints only 3
            }
        });
    };
}

提前致谢...

提问于
用户回答回答于

FileReader性质是你无法使其操作同步。

我怀疑你并不真正需要或希望它是同步的,只是你想要正确获得结果URL。如果是这样,我不认为承诺会真的有帮助。相反,只需跟踪您有多少未完成的操作,以便在完成后知道:

var inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = function(){
    var data = [];      // The results
    var pending = 0;    // How many outstanding operations we have

    // Schedule reading all the files (this finishes before the first onload
    // callback is allowed to be executed)
    Array.prototype.forEach.call(inputFiles.files, function(file, index) {
        // Read this file, remember it in `data` using the same index
        // as the file entry
        var fr = new FileReader();
        fr.onload = function() {
            data[index] = fr.result;
            --pending;
            if (pending == 0) {
                // All requests are complete, you're done
            }
        }
        fr.readAsDataURL(file);
        ++pending;
    });
}

或者,如果由于某种原因要按顺序(但仍然是异步)读取文件,则可以通过仅在前一个调用完成时调度下一个调用来执行此操作:

// Note: This assumes there is at least one file, if that
// assumption isn't valid, you'll need to add an up-front check
var inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = function(){
    var index = 0;

    readNext();

    function readNext() {
        var file = inputFiles.files[index++];
        var fr = new FileReader();
        fr.onload = function() {
            // use fr.result here
            if (index < inputFiles.files.length) {
                // More to do, start loading the next one
                readNext();
            }
        }
        fr.readAsDataURL(file);
    }
}
用户回答回答于
function readFile(file){
  return new Promise((resolve, reject) => {
    var fr = new FileReader();  
    fr.onload = () => {
      resolve(fr.result )
    };
    fr.readAsText(file.blob);
  });
}

扫码关注云+社区

领取腾讯云代金券