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

Node.js中async函数执行顺序及then与await差异疑问

Node.js异步执行逻辑与await/then差异解析

核心问题解答

你看到的执行顺序是JavaScript异步非阻塞特性导致的,并非task1在await sleep(1)前中断。具体流程如下:

  1. 调用task1(),同步执行console.log("task1 doing");
  2. 执行await sleep(1):sleep返回一个pending状态的Promise,此时JS引擎暂停task1的后续执行,将控制权交还给事件循环;
  3. 事件循环继续执行下一个任务:调用task2(),同步执行console.log("task2"),task2返回resolved状态的Promise;
  4. task2().then(...)的回调被加入微任务队列,立即执行console.log(2);
  5. 1秒后,setTimeout触发,sleep的Promise变为resolved,JS引擎恢复task1的执行,同步执行console.log("task1 done");
  6. task1的Promise变为resolved,task1().then(...)的回调执行console.log(1)。

await与then的核心差异

1. 执行顺序控制

  • await:会暂停当前async函数的执行,等待Promise状态变更(resolved/rejected)后,再继续执行函数内await之后的代码。它把异步操作“伪装”成同步的顺序执行逻辑。
    比如你第二个例子里的await task1(); await task2();,必须等task1的所有逻辑(包括await后的代码)全部完成,才会启动task2。
  • then:是给Promise注册回调函数,当前函数不会暂停,会继续执行后续代码。回调函数会在Promise变为resolved后,被加入微任务队列等待执行。
    第一个例子里,task1().then(...)和task2().then(...)是两个独立的异步任务,它们的执行顺序由各自Promise的状态变更时间决定。

2. 代码可读性与写法

  • await:采用“同步式”写法,逻辑线性,更易理解和维护,尤其适合复杂的串行异步场景。
  • then:采用链式调用写法,适合简单异步流或需要并行处理多个Promise的场景(比如Promise.all配合then)。

3. 错误处理

  • await:搭配try/catch捕获错误,符合同步代码的错误处理习惯:
    async function callTask() {
      try {
        await task1();
        await task2();
      } catch (err) {
        console.error(err);
      }
    }
    
  • then:通过链式调用.catch()方法捕获错误,或者在then的第二个参数传入错误回调:
    task1()
      .then(() => task2())
      .catch(err => console.error(err));
    

总结

  • 当需要严格的串行异步执行时,用await更直观;
  • 当需要并行处理多个异步任务,或者不想阻塞当前函数执行时,用then更灵活;
  • JavaScript的异步机制基于事件循环,await本质上是Promise.then的语法糖,但提供了更线性的代码逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 03:42:36