async/await 原理与 Promise 对照
1. 核心原理
async/await 是基于 Promise 的语法糖。它没有改变 JavaScript 的异步模型,只是让 Promise 链可以写得更接近同步代码。
async:保证函数返回一个 Promise。await:等待一个 Promise 的结果,并暂停当前async函数后续代码的执行。await后面的代码:相当于放进.then()回调,会在微任务中继续执行。try/catch:相当于 Promise 链末尾的.catch()。
先看一个最小对照。
async/await 写法
Promise 写法
两段代码的核心流程完全相同:
2. 执行顺序对照
面试中经常考 await 前后代码的执行时机。
async/await 写法
等价的 Promise 写法
两段代码的输出相同:
执行过程如下:
- 输出
script start。 - 调用
async1(),同步输出async1 start。 - 调用
async2(),函数体立即执行,同步输出async2。 await后面的代码等价于.then()回调,被加入微任务队列。- 主线程继续执行,同步输出
script end。 - 当前同步代码结束后,执行微任务,输出
async1 end。
关键不是“看到 await 就立即异步”,而是:
await右侧的表达式会先执行,await后面的代码才会延后到微任务中执行。
3. 错误处理对照
async/await 可以用 try/catch 统一处理多个异步步骤的错误。
async/await 写法
等价的 Promise 写法
对应关系是:
如果希望调用方继续处理错误,两种写法都不要在当前函数中把错误“吞掉”:
4. 串行执行对照
当 B 必须等 A 完成后才能开始时,需要串行执行。
async/await 写法
等价的 Promise 写法
执行过程是:
两种写法中,fetchB() 都是在 A 完成后才被调用,因此总耗时大约是两个请求耗时之和。
5. 并行执行对照
如果 A 和 B 互不依赖,应当同时启动。
async/await 写法
等价的 Promise 写法
也可以在 async 函数中直接使用 Promise.all:
执行过程是:
这里实现并行的关键不是 await,而是 fetchA() 和 fetchB() 在等待结果之前就都已经被调用。
6. 返回值与异常对照
返回普通值
两种写法调用后得到的都是一个以 42 为结果的 Promise。
抛出异常
两种写法调用后得到的都是 rejected Promise,而不是直接把异常抛给函数调用处。
7. 面试总结
可以把常见写法记成下面的对应关系:
面试时可以这样回答:
async/await是基于 Promise 的语法糖。async函数一定返回 Promise;await会先执行右侧表达式,再暂停当前函数,把后续代码放到微任务中继续执行。连续的await对应连续的.then(),try/catch对应.catch()。如果多个异步任务互不依赖,应先同时启动,再使用Promise.all()等待结果,避免无意中串行执行。
补充:ES2022 允许在 ES Module 顶层使用 await,无需包裹在 async 函数中。

