异步任务执行顺序
异步任务执行顺序
console.log(1);async function foo() {console.log(2);await bar(); // 关键点:await 会暂停 foo 的执行console.log(3); // 被放入微任务队列(在 bar 的 Promise 解决后)
}async function bar() {console.log(4);await Promise.resolve(); // 暂停 bar 的执行console.log(5); // 被放入微任务队列
}setTimeout(() => console.log(6), 0); // 宏任务foo();new Promise(resolve => {console.log(7);resolve();
}).then(() => console.log(8)); // 微任务console.log(9);
执行步骤详解:
-
同步代码执行:
console.log(1)
→ 输出1
- 调用
foo()
:console.log(2)
→ 输出2
- 调用
bar()
:console.log(4)
→ 输出4
await Promise.resolve()
暂停bar
,将console.log(5)
放入微任务队列
await bar()
暂停foo
,将console.log(3)
标记为等待(但尚未入队)
new Promise
同步执行:console.log(7)
→ 输出7
resolve()
→ 将console.log(8)
放入微任务队列
console.log(9)
→ 输出9
- 当前输出:
1, 2, 4, 7, 9
-
微任务队列处理:
- 微任务队列初始内容:
[输出5, 输出8]
- 执行第一个微任务:
console.log(5)
→ 输出5
- 关键:此时
bar()
的 Promise 解决,触发foo()
的等待结束 foo()
中的console.log(3)
被放入微任务队列
- 关键:此时
- 执行第二个微任务:
console.log(8)
→ 输出8
- 执行第三个微任务:
console.log(3)
→ 输出3
- 输出:
5, 8, 3
- 微任务队列初始内容:
-
宏任务队列处理:
- 执行
setTimeout
回调:console.log(6)
→ 输出6
- 执行
最终输出顺序:
1 → 2 → 4 → 7 → 9 → 5 → 8 → 3 → 6
关键机制说明:
-
await
的双重暂停:await bar()
暂停foo
时,console.log(3)
不会立即入队- 必须等待
bar()
的 Promise 解决(即console.log(5)
执行后),console.log(3)
才加入微任务队列
-
微任务执行顺序:
-
优先级规则:
- 同步代码 > 已存在的微任务 > 新生成的微任务 > 宏任务
- 微任务队列按 先进先出 (FIFO) 顺序执行
常见误区:
- 误认为
await
后的代码会立即入队(实际需等待右侧 Promise 解决) - 忽略链式微任务的动态生成(如
console.log(3)
在console.log(5)
执行后才入队) - 混淆微任务和宏任务的优先级(微任务总是优先于宏任务)
你的理解完全正确!这个顺序展示了 JavaScript 事件循环的精细调度机制。