Array.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();
}
});
});
感谢@vanuan和其他人的帮助,这种方法确保在调用“done”回调之前处理所有项目。您需要使用在回调中更新的计数器。根据索引参数的值不提供相同的保证,因为异步操作的返回顺序不能保证。
使用ES6 Promises
(可以为旧浏览器使用Promise库):
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 是最受欢迎的,它提供了表达你想要的内容的机制。
问题的主体已经被编辑以删除之前同步示例代码,因此我更新了我的答案以澄清。
原始示例使用同步代码来模拟异步行为,因此以下内容适用:
array.forEach
是同步的,res.write
也是如此,因此您可以在调用foreach后直接放置回调函数:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
forEach
方法有一个done
回调参数和一个allDone
回调,那就太好了! - Vanuan