正如 Headers 所示 . 我该怎么做呢?
在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!
13 回答
Array.forEach
没有提供这种精确性(哦,如果它会)但有几种方法可以实现你想要的:使用简单的计数器
(感谢@vanuan和其他人)这种方法保证在调用“完成”回调之前处理所有项目 . 您需要使用在回调中更新的计数器 . 取决于索引参数的值不提供相同的保证,因为不保证异步操作的返回顺序 .
使用ES6承诺
(promise库可用于旧版浏览器):
使用异步库
还有其他异步库,async是最受欢迎的,提供表达您想要的机制 .
编辑
问题的主体已被编辑,以删除以前的同步示例代码,所以我已更新我的答案澄清 . 原始示例使用同步代码来模拟异步行为,因此应用了以下内容:
array.forEach
是synchronous,因此是res.write
,因此您可以在调用foreach后简单地进行回调:如果你遇到异步函数,并且你想确保在执行代码之前完成它的任务,我们总是可以使用回调功能 .
例如:
注意:functionAfterForEach是在foreach任务完成后执行的函数 . asynchronous是在foreach中执行的异步函数 .
希望这可以帮助 .
很奇怪有多少错误答案给了异步案例!可以简单地显示检查索引不提供预期的行为:
输出:
如果我们检查
index === array.length - 1
,将在完成第一次迭代时调用回调,而第一个元素仍处于未决状态!为了在不使用异步等外部库的情况下解决这个问题,我认为最好的办法是保存列表的长度,并在每次迭代后减少 . 由于只有一个线程,我们确信没有竞争条件的可能性 .
希望这能解决你的问题,当我需要执行forEach内部的异步任务时,我通常会使用它 .
同
我的解决方案没有Promise(这确保每个操作在下一个操作开始之前结束):
使用ES2018,您可以使用异步迭代器:
这是Node.js的解决方案,它是异步的 .
使用async npm包 .
(JavaScript) Synchronizing forEach Loop with callbacks inside
我的解决方案
例:
我尝试使用Easy Way解决它,与您分享:
request
是节点js中mssql库的功能 . 这可以替换您想要的每个功能或代码 . 祝好运setInterval如何检查完整的迭代次数,带来保证 . 不确定它是否会超载范围,但我使用它,似乎是一个
一个简单的解决方案就像跟随
您不需要回调来遍历列表 . 只需在循环后添加
end()
调用即可 .