正如标题所示。我怎么做呢?
我想在foreach循环遍历每个元素并完成一些异步处理后调用whenAllDone()。
[1, 2, 3].forEach(
function(item, index, array, done) {
asyncFunction(item, function itemDone() {
console.log(item + " done");
done();
});
}, function allDone() {
console.log("All done");
whenAllDone();
}
);
有可能让它这样工作吗?当forEach的第二个参数是一个回调函数,当它经过所有迭代时运行?
预期的输出:
3 done
1 done
2 done
All done!
在这个帖子中有许多解决方案和方法来实现这一点!
但是,如果你需要用map和async/await来做这个,那么这里就是
// Execution Starts
console.log("start")
// The Map will return promises
// the Execution will not go forward until all the promises are resolved.
await Promise.all(
[1, 2, 3].map( async (item) => {
await asyncFunction(item)
})
)
// Will only run after all the items have resolved the asynchronous function.
console.log("End")
输出将如下所示!可能根据异步函数而有所不同。
start
2
3
1
end
注意:如果你在map中使用await,它总是会返回promises数组。
数组中。forEach并没有提供这样的细节(如果可以的话),但是有几种方法可以实现你想要的:
使用一个简单的计数器
function callback () { console.log('all done'); }
var itemsProcessed = 0;
[1, 2, 3].forEach((item, index, array) => {
asyncFunction(item, () => {
itemsProcessed++;
if(itemsProcessed === array.length) {
callback();
}
});
});
这种方法保证在调用"done"回调之前处理所有项。您需要使用一个在回调中更新的计数器。依赖于索引参数的值并不能提供相同的保证,因为异步操作的返回顺序是不能保证的。
使用ES6承诺
(一个承诺库可以用于较旧的浏览器):
Process all requests guaranteeing synchronous execution (e.g. 1 then 2 then 3)
function asyncFunction (item, cb) {
setTimeout(() => {
console.log('done with', item);
cb();
}, 100);
}
let requests = [1, 2, 3].reduce((promiseChain, item) => {
return promiseChain.then(() => new Promise((resolve) => {
asyncFunction(item, resolve);
}));
}, Promise.resolve());
requests.then(() => console.log('done'))
Process all async requests without "synchronous" execution (2 may finish faster than 1)
let requests = [1,2,3].map((item) => {
return new Promise((resolve) => {
asyncFunction(item, resolve);
});
})
Promise.all(requests).then(() => console.log('done'));
使用异步库
还有其他异步库,async是最流行的,它们提供了表达所需内容的机制。
Edit
问题的主体已被编辑以删除之前的同步示例代码,因此我更新了我的答案以澄清。
最初的例子使用了类似于同步的代码来模拟异步行为,因此应用了以下内容:
数组中。forEach是同步的,res.write也是同步的,所以你可以简单地把你的回调放在你调用forEach之后:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
希望这将解决你的问题,我通常与此工作时,我需要执行forEach与异步任务。
foo = [a,b,c,d];
waiting = foo.length;
foo.forEach(function(entry){
doAsynchronousFunction(entry,finish) //call finish after each entry
}
function finish(){
waiting--;
if (waiting==0) {
//do your Job intended to be done after forEach is completed
}
}
与
function doAsynchronousFunction(entry,callback){
//asynchronousjob with entry
callback();
}