ECMA6中的承诺:如何修改承诺以在承诺已经在函数中返回后保持其解析值

Promises in ECMA6: How to modify promise to hold its resolved value after that promise has already been returned in a function?

本文关键字:承诺 返回 函数 何修改 ECMA6 修改      更新时间:2023-09-26

这里有一个方法,它接受一个文件数组(HTML5文件API中的文件),并使用一个承诺来返回文件中的文本,因为读取是一个异步操作。问题是,当我在另一个方法中访问文本时,它仍然包含已经解决的承诺对象,但我想用实际的文本本身替换那些承诺。return语句在promise被解析之前被调用,所以我不完全确定该怎么做。

function getTextFromJsonFiles(files) {
 var texts = [];
 var reader = new FileReader();
 for (let file of files) {
    var textPromise = new Promise(function (resolve, reject) {
        reader.readAsText(file);
        reader.onload = function (evt) {
            resolve(evt.target.result);
        };
    });

    texts.push(textPromise);
}
return texts;
 }

getTextFromJsonFiles应该返回一个承诺,该承诺解析为其他承诺的值。这可以很容易地通过Promise.all实现:

return Promise.all(texts);

用法:

getTextFromJsonFiles(...).then(texts => {
  console.log(texts);
});

我也不认为你可以这样重用reader。如果并行化文件读取,则必须为每个文件创建单独的读取器。下面是你的函数的更正版本:

function getTextFromJsonFiles(files) {
  return Promise.all(files.map(file => new Promise(resolve => {
    var reader = new FileReader();
    reader.readAsText(file);
    reader.onload = evt => resolve(evt.target.result);
  })));
}

如果您想返回异步进程数组,则应该使用Promise.all。所以你的函数应该返回一个promise,调用函数应该解析它。

function getTextFromJsonFiles(files) {
    var textPromises = [];
    var reader = new FileReader();
    for (let file of files) {
        var textPromise = new Promise(function (resolve, reject) {
            reader.readAsText(file);
            reader.onload = function (evt) {
                resolve(evt.target.result);
            };
            reader.onerror = reject; // if any error occurs promise should  reject the result
        });
        textPromises.push(textPromise);
    }
    return Promise.all(textPromises);
}

那么你可以这样使用getTextFromJsonFiles:

getTextFromJsonFiles(files).then(function(texts){
     //process texts here
}).catch(function(error){
     //if any one of the text promises fail, this function will be called, you can handle error here.
})

关于如何使用FileReader,请查看@felix-kling的回答