Node.js中async函数执行顺序及then与await差异疑问
Node.js异步执行逻辑与await/then差异解析
核心问题解答
你看到的执行顺序是JavaScript异步非阻塞特性导致的,并非task1在await sleep(1)前中断。具体流程如下:
- 调用
task1(),同步执行console.log("task1 doing"); - 执行
await sleep(1):sleep返回一个pending状态的Promise,此时JS引擎暂停task1的后续执行,将控制权交还给事件循环; - 事件循环继续执行下一个任务:调用
task2(),同步执行console.log("task2"),task2返回resolved状态的Promise; task2().then(...)的回调被加入微任务队列,立即执行console.log(2);- 1秒后,
setTimeout触发,sleep的Promise变为resolved,JS引擎恢复task1的执行,同步执行console.log("task1 done"); 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
相关产品推荐
相关产品推荐

