for of ,map ,forEach体内异步操作的区别

for of ,map ,forEach体内异步操作的区别

1. for...of循环

for...of循环用于遍历可迭代对象(如 Array, String, Map, Set 等),它会依次取出每个元素的值进行处理

执行机制:循环会同步地、按顺序依次处理每个元素,只有所有元素都处理完毕,循环才会结束

与异步结合:for...of循环本身是同步的。但如果循环体内有异步操作(如 await),它可以配合 await关键字,等待当前异步操作完成后再进行下一次迭代

这是它与 forEach在处理异步任务时的一个关键区别。

//for...of循环允许你使用 await关键字,从而确保异步操作会按照数组元素的顺序一个一个地完成。
async function processArray(array) {
  for (const item of array) {
    // 等待当前异步操作完成后再进行下一次迭代
    const result = await asyncFunction(item);
    console.log(result);
  }
  console.log('所有操作已完成!');
}

2.map

map()方法是同步的。图表中“执行回调函数”这一步是立即发生的,它会等待当前回调函数完全执行完毕(包括其内部任何同步代码)后,才会继续处理下一个元素

image.png

map()不会修改原数组,而是生成一个全新的数组。

与异步操作结合:map()本身并不关心回调函数的返回值是否是 Promise。即便回调函数返回 Promise,map()仍会立即返回一个包含这些 Promise 对象的普通数组,而不会“等待”这些 Promise 完成。

若需处理包含异步任务的数组映射,并等待所有异步任务完成,通常需配合 Promise.all()使用:

//如果你希望所有异步操作同时发起,然后等待它们全部完成,可以使用 Promise.all配合 map方法。
async function processArrayParallel(array) {
  // 使用map创建出一个Promise数组
  const promises = array.map(item => asyncFunction(item));
  // 并行等待所有Promise完成
  const results = await Promise.all(promises);
  console.log(results); // 结果数组的顺序与原始数组一致
  console.log('所有并行操作已完成!');
}

注意:Promise.all具有“快速失败”的特性,即如果其中任何一个 Promise 被拒绝(reject),整个 Promise.all会立即被拒绝。如果需要等待所有操作完成(无论成功或失败),可以使用 Promise.allSettled。

3.forEach

forEach的机制是同步遍历数组,并为每个元素立即发起一个回调函数。对于回调函数内部的异步操作,forEach不会等待它们完成,而是继续同步执行下一个循环。所有这些异步操作都会被“挂起”,放入任务队列,等待当前所有同步代码(包括整个 forEach循环)执行完毕后,事件循环才会来处理它们。这就导致了异步操作完成顺序的不可控

总结:

  • forEach+ 异步 = 预期外的结果。尽量避免这样使用
    根据你是想顺序执行还是并行执行来选择正确的工具:
  • 顺序执行 → for...of+ await
  • 并行执行 → Promise.all()+ array.map()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容