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

JS面试题:如何改造代码使所有setTimeout执行完后再输出Completed

问题原因分析

原代码的setTimeout是异步非阻塞API,调用后会直接进入事件循环等待触发,不会阻塞主线程执行。因此循环调用callMe后主线程会立即执行console.log('Completed'),等到对应延迟时间到了才会依次打印三次Called,和预期输出顺序不符。

改造方案

按照提示使用await关键字改造,需要做两处核心调整:

  • 改造callMe函数,让它返回Promise实例,await只能等待Promise状态变更后才会继续执行后续代码
  • 将循环和最终打印逻辑包裹在async作用域内(await必须在async标记的作用域中使用)

改造后的完整代码如下:

// 改造callMe返回Promise
function callMe(delay) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('Called');
      resolve(); // 异步逻辑执行完成后变更Promise状态
    }, delay);
  })
}

const delays = [500, 1000, 1500];

// 用async立即执行函数包裹异步逻辑
(async () => {
  for (let delay of delays) {
    await callMe(delay); // 等待当前callMe执行完成再进入下一次循环
  }
  console.log('Completed');
})();

如果运行环境支持顶层await(比如ES模块、现代浏览器、Node.js 14.8+版本),可以省略立即执行函数,直接写:

for (let delay of delays) {
  await callMe(delay);
}
console.log('Completed');

可选优化:并发执行减少总耗时

上面的写法是串行执行三个异步调用,总耗时为500+1000+1500=3000ms,如果希望三个调用并发执行,总耗时只需要1500ms,可以用Promise.all实现:

(async () => {
  await Promise.all(delays.map(delay => callMe(delay)));
  console.log('Completed');
})();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 23:15:03