You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何forEach与for-of遍历异步调用时响应顺序及耗时不同?

JavaScript异步函数在循环中的执行逻辑疑问与解答

问题背景

代码片段

const sleep = async(delay, input) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(input);
    }, delay);
  });
};

const promises = [sleep(500, 1), sleep(1000, 3), sleep(750, 2)];

(async() => {
  console.time('runTime');
  const res1 = [];
  const res2 = [];

  promises.forEach(async(promise) => {
    const res = await promise;
    res1.push(res);
  });

  console.log('logging forEach loop response-1', res1);

  for (const promise of promises) {
    const res = await promise;
    res2.push(res);
  }

  console.log('logging forEach loop response-2', res1);
  console.log('logging for loop response', res2);

  console.timeEnd('runTime');
})();

执行输出

logging forEach loop response-1 []
logging forEach loop response-2 [ 1, 2, 3 ]
logging for loop response [ 1, 3, 2 ]
runTime: 1.011s

核心疑问

  1. 为何整个代码仅耗时约1秒?我理解logging forEach loop response-1输出空数组是因为forEach的回调是异步的,但forEach本身并非异步,执行完后数组尚未填充;但for-of循环依次await每个Promise,按计算应耗时0.5+1+0.75=2.25秒,为何实际并非如此?
  2. 为何logging forEach loop response-2的输出按延迟顺序排列,而logging for loop response按原Promise数组顺序排列?我猜测forEach会创建独立的匿名回调实例,回调按延迟顺序resolve,但结合疑问1,仍无法理解for-of的耗时为何不是2.25秒。

解答

疑问1:总耗时为何约1秒?

核心原因是Promise的创建时机:当你定义promises数组时,三个sleep函数已经被调用,内部的setTimeout已经开始计时——三个Promise是同时启动的,不是等到for-of循环里的await才开始执行。

for-of循环中的await promise只是等待已经在运行的Promise完成,而非从头触发执行。三个Promise里最长的延迟是1秒,所以整个代码的总耗时由这个最长的Promise决定,最终约1秒,而非三个延迟时间相加的2.25秒。

疑问2:两个数组的顺序差异原因

  • res1(forEach循环):forEach会立即遍历所有Promise,给每个Promise绑定独立的异步回调。每个回调中的await promise会等对应Promise完成后,再把结果push进res1。三个Promise的完成顺序是:500ms的(值1)→750ms的(值2)→1000ms的(值3),所以res1最终是[1,2,3]。
  • res2(for-of循环):for-of严格按照原数组的顺序处理每个Promise。哪怕某个Promise已经提前完成(比如第一个500ms的Promise),代码也会先await它并push结果1;接着处理第二个Promise(延迟1000ms),等它完成后push结果3;最后处理第三个Promise(延迟750ms,此时已经完成),push结果2。因此res2的顺序和原Promise数组一致,是[1,3,2]。

内容的提问来源于stack exchange,提问作者pythoniesta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:12:47