如何在JavaScript中按顺序或并行运行异步循环?
在进行异步魔术之前,我想提醒您经典同步循环是什么样的。
同步循环
很久以前,我以这种方式编写了循环(也许您也是如此):
for (var i=0; i < array.length; i++) { var item = array[i];
这个周期既好又快。 但是他在可读性和支持方面存在很多问题。 一段时间后,我习惯了最佳版本:
array.forEach((item) => {
JavaScript发展很快。 出现新功能和语法。 我最喜欢的增强功能之一是async / await 。
现在,我经常使用这种语法。 有时在某些情况下,我需要异步处理数组元素。
异步循环
如何在循环体内使用await
? 让我们尝试编写一个异步函数,并期待处理每个元素的任务:
async function processArray(array) { array.forEach(item => {
此代码将引发错误。 怎么了 因为我们不能在同步函数中使用await
。 如您所见, processArray
是一个异步函数。 但是我们为forEach
使用的匿名函数是同步的 。
该怎么办?
1.不要等待执行结果
我们可以将匿名函数定义为异步的:
async function processArray(array) { array.forEach(async (item) => { await func(item); }) console.log('Done!'); }
但是forEach
不会等待任务完成。 forEach
是一个同步操作。 她将只是启动任务并继续前进。 让我们检查一个简单的测试:
function delay() { return new Promise(resolve => setTimeout(resolve, 300)); } async function delayedLog(item) {
在控制台中,我们将看到:
Done! 1 2 3
在某些情况下,这可能是正常结果。 但是,在大多数情况下,这不是合适的逻辑。
2.按顺序处理循环
为了等待循环体执行的结果,我们需要返回到旧的“ for”循环。 但是这次,我们将使用其新版本与for..of
构造(感谢迭代协议 ):
async function processArray(array) { for (const item of array) { await delayedLog(item); } console.log('Done!'); }
这将给我们预期的结果:
1 2 3 Done!
数组的每个元素将被顺序处理。 但是我们可以并行运行循环!
3.并行处理循环
您需要稍微修改代码以并行开始操作:
async function processArray(array) {
此代码可以并行运行多个delayLog
任务。 但是要小心使用大型阵列。 对于CPU和内存来说,太多任务可能太难了。
另外,请不要将示例中的“并行任务”与真正的并行性和线程混淆。 此代码不保证并行执行。 一切都取决于循环的主体(在示例中,它是delayedLog
)。 网络请求,网络工作者和其他一些任务可以并行执行。