请详细描述 JavaScript 的事件循环(Event Loop)机制
JavaScript 是单线程语言,通过事件循环实现异步非阻塞。
执行栈与任务队列
- 执行栈(Call Stack):同步代码按顺序入栈执行
- 微任务队列(Microtask Queue):
Promise.then、queueMicrotask、MutationObserver - 宏任务队列(Macrotask Queue):
setTimeout、setInterval、I/O、UI rendering
事件循环流程
1. 执行同步代码(执行栈清空)
2. 执行所有微任务(清空微任务队列)
3. 执行一个宏任务
4. 回到步骤 2经典示例
console.log('1') // 同步
setTimeout(() => console.log('2'), 0) // 宏任务
Promise.resolve().then(() => {
console.log('3') // 微任务
}).then(() => {
console.log('4') // 微任务
})
console.log('5') // 同步
// 输出:1 → 5 → 3 → 4 → 2执行过程
- 同步代码:
1、5先输出 - 微任务队列:
3、4输出 - 宏任务队列:
2输出
Node.js 中的事件循环
Node.js 有更复杂的阶段模型:
timers → pending callbacks → idle, prepare → poll → check → close callbacksprocess.nextTick优先级高于所有微任务setImmediate在 check 阶段执行
关键点
- 微任务在每次宏任务后全部执行完,不是只执行一个
async/await本质是 Promise 的语法糖,await后的代码相当于.then()