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

async/await函数执行行为异常:输出不符预期求技术解答

为什么两次调用start()会导致异步执行顺序混乱?

问题的核心是你连续调用了两次start()函数,这两个start()是并行执行的,它们之间没有任何等待机制。每个start()内部的for循环因为await是串行执行的,但两个独立的start()调用会同时启动,导致它们的异步任务互相穿插,出现你看到的混乱输出。

详细执行流程拆解

我们一步步捋清楚代码的执行顺序:

  1. 第一次调用start():
    • 进入for循环(i=0),执行delayToRun(),立即打印first delay。
    • 遇到await new Promise(...),此时start()的第一个循环暂停,JavaScript引擎释放线程去执行其他任务。
  2. 紧接着第二次调用start():
    • 同样进入for循环(i=0),执行delayToRun(),立即打印first delay。
    • 遇到await new Promise(...),这个start()的第一个循环也暂停,引擎继续等待任务触发。
  3. 2秒后,两个setTimeout同时触发,对应的Promise被resolve:
    • 先处理第一个start()暂停的代码:打印second delay,返回Done,接着打印Done和分割线。然后进入i=1,执行delayToRun(),打印first delay,再次遇到await暂停。
    • 接着处理第二个start()暂停的代码:打印second delay,返回Done,打印Done和分割线。然后进入i=1,执行delayToRun(),打印first delay,遇到await暂停。
  4. 又过2秒,新的两个setTimeout触发:
    • 处理第一个start()的i=1暂停代码:打印second delay、Done和分割线。
    • 处理第二个start()的i=1暂停代码:打印second delay、Done和分割线。

这就是为什么你看到输出里两个first delay先一起出现,之后是穿插的执行结果——因为两个start()完全是并行启动的,互相不等待对方完成。

实现全串行执行的修正方案

如果你希望两次start()调用也按顺序执行,需要让第二个start()等待第一个完成,修改代码如下:

const delayToRun = async() => {
  console.log('first delay');
  let p = await new Promise((resolve, reject) => {
    setTimeout(() => resolve('Done'), 2000);
  });
  console.log('second delay');
  return p;
};

const start = async() => {
  for (let i = 0; i < 2; i++) {
    const res = await delayToRun();
    console.log(res);
    console.log('--------------------------------');
  }
};

// 让第二个start()等待第一个执行完成后再启动
start().then(() => start());

修正后的执行输出会符合你最初的预期:

first delay
second delay
Done
--------------------------------
first delay
second delay
Done
--------------------------------
first delay
second delay
Done
--------------------------------
first delay
second delay
Done
--------------------------------

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:15:34