forEach 中使用 await

forEach 不支持 await,使用 for...of 或 for 循环代替

问题

forEach 中使用 await 无法按预期顺序执行异步操作。

async function test() {
  let arr = [3, 2, 1];
  arr.forEach(async (item) => {
    const res = await fetch(item);
    console.log(res);
  });
  console.log("end");
}

function fetch(x) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(x);
    }, 500 * x);
  });
}

test();

输出结果:

end
1
2
3

解答

原因

forEach 只支持同步代码,不会等待异步操作完成。参考 Polyfill 实现:

while (index < arr.length) {
  callback(item, index); // 直接调用回调函数,不处理异步
}

forEach 只是简单执行回调函数,不会处理 async 函数返回的 Promise。

解决方案 1:for…of

async function test() {
  let arr = [3, 2, 1];
  for (const item of arr) {
    const res = await fetch(item);
    console.log(res);
  }
  console.log("end");
}

输出结果:

3
2
1
end

解决方案 2:for 循环

async function test() {
  let arr = [3, 2, 1];
  for (let i = 0; i < arr.length; i++) {
    const res = await fetch(arr[i]);
    console.log(res);
  }
  console.log("end");
}

关键点

  • forEach 直接调用回调函数,不等待 Promise 完成
  • for...of 通过迭代器遍历,支持 await 暂停执行
  • 传统 for 循环同样支持 await
  • forEach 中使用 break 也无法中断遍历