基本上,我正在寻找像Promise.all()
这样的东西,但是只要结果准备好就会为每个结果调用then()
中的函数。使用像这样的标准回调(文件阅读示例)来编写它是微不足道的:
function foo(files, bar) {
for (let file of files) {
const fr = new FileReader();
fr.onload = e => bar(e.target.result);
fr.readAsDataURL(file);
}
}
我确信那里有一个可以满足我想要的库,但是我想在纯JS中做到这一点。
澄清一下,我想有这样的事情:
function foo(files) {
// do something here;
}
foo(['1','2','3']).then(/* do something here with separate results */);`
答案 0 :(得分:4)
只需使用map
:
let read = file => return new Promise(resolve => {
const fr = new FileReader();
fr.onload = e => resolve(e.target.result);
fr.readAsDataURL(file);
});
Promise.all(files.map(file => read(file).then(bar)))
.then(allResultsFromBar => { /* use results array */ });
请注意.then
将从它执行的函数返回的任何内容提升为一个promise(即它隐式调用Promise.resolve
),因此Promise.all
保证接收一个promise数组no无论bar
返回什么。
答案 1 :(得分:0)
使用@ jib的回答和评论:
我想要一个函数readFiles,它将文件列表作为唯一的参数,我希望它返回一些我可以调用then()的承诺,以及我将放入的函数( )将为每个文件单独调用。
这是不可能的,因为.then()
回调只被调用一次,而不是Promise.all()
每次传递一次。
这很接近:
let read = file => return new Promise((resolve, reject) => {
const fr = new FileReader();
fr.onload = e => resolve(e.target.result);
fr.onerror = reject; // don't forget to reject on error
fr.readAsDataURL(file);
});
let readFiles = files => return Promise.all(files.map(read)); // <<<<< this is the line you seek
允许你写:
const files = ["...", "...", "..."];
readFiles(files)
.then(allFileResults => allFileResults.map(bar)); // bar is your function for processing file results
// possibly chain another .then() if required to observe/process bar()'s results
因此bar()
将依次对每个文件内容进行操作。
然而,在使代码尽可能接近您的要求时:
allFileContents.map(bar)
进程位于Promise.all()
的下游,因此在开始bar()
调用之前,等待所有文件被读取。readFiles(...)
中的任何一个错误(没有某种错误恢复)会破坏整个企业;永远不会在任何文件上调用allFileContents.map(bar)
;根据您的申请,这可能是好的或坏的;但好消息是,很容易插入错误恢复。bar()
必须是同步的;如果没有,您只需插入另一个Promise.all()
,即allFileResults => Promise.all(allFileResults.map(bar))
。由于这些原因,@ jib的解决方案可能是最适合的解决方案,但这取决于应用程序的要求。