这道题其实是 async / await + Promise + 事件循环 的经典执行顺序题。
核心是理解:
async函数 会立即执行同步代码await相当于 Promise.then(微任务)async函数 默认返回 Promiseawait后面的代码 会被放入微任务队列
我们一步一步拆。
一、代码结构
代码大致是:
console.log(1)
async function async1() {
await async2()
console.log(2)
await async3()
console.log(3)
}
async function async2() {
console.log(4)
}
async function async3() {
console.log(5)
}
async1()
console.log(6)
二、执行流程
1 先执行同步代码
第一行:
console.log(1)
输出
1
2 执行 async1()
async1()
进入 async1
执行
await async2()
先执行 async2()
3 执行 async2()
async function async2() {
console.log(4)
}
这是同步代码:
输出
4
async2() 返回
Promise.resolve(undefined)
所以
await async2()
等价于
Promise.resolve().then(...)
于是:
console.log(2)
被放入 微任务队列
4 回到主线程继续执行
继续往下执行同步代码:
console.log(6)
输出
6
三、开始执行微任务
此时微任务队列有:
console.log(2)
执行:
2
5 执行 await async3()
await async3()
先执行 async3()
async3()
console.log(5)
输出
5
返回
Promise.resolve()
于是
console.log(3)
进入 新的微任务
四、执行最后微任务
输出
3
五、最终输出顺序
1
4
6
2
5
3
六、一张流程图理解
主线程
│
├─ console.log(1)
│
├─ async1()
│ │
│ ├─ async2()
│ │ └─ console.log(4)
│ │
│ └─ await → 微任务(console.log(2))
│
├─ console.log(6)
│
└─ 执行微任务
│
├─ console.log(2)
│
├─ async3()
│ └─ console.log(5)
│
└─ 微任务(console.log(3))
七、面试官最想听的总结
一句话版本:
await 会暂停 async 函数,把后面的代码放进微任务队列。
所以执行顺序遵循:
同步代码
→ 微任务 (Promise.then / await)
→ 宏任务 (setTimeout)
八、一个更本质的理解(高级面试)
很多人不知道:
await asyncFn()
真正等价于
Promise.resolve(asyncFn()).then(() => {
// await 后面的代码
})
所以:
await = Promise.then(微任务)