JavaScript 事件循环(Event Loop)
JavaScript 是单线程语言,通过事件循环实现异步非阻塞执行。
核心组件
JavaScript
┌─────────────────────────────┐
│ 调用栈 (Call Stack) │
├─────────────────────────────┤
│ 微任务队列 │
│ (Promise.then/MutationObserver) │
├─────────────────────────────┤
│ 宏任务队列 │
│ (setTimeout/setInterval/I/O) │
└─────────────────────────────┘
执行顺序
- 执行同步代码(调用栈)
- 调用栈清空后,检查微任务队列
- 执行所有微任务
- 执行一个宏任务
- 循环步骤 2-4
宏任务与微任务
| 类型 | 宏任务 | 微任务 |
|---|---|---|
| 计时器 | setTimeout, setInterval | - |
| Promise | - | Promise.then/catch/finally |
| DOM | I/O, UI渲染 | MutationObserver |
| Node.js | setImmediate, I/O | process.nextTick |
| 其他 | requestAnimationFrame | queueMicrotask |
经典示例
JavaScript
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
Promise.resolve().then(() => {
console.log('3');
});
console.log('4');
// 输出顺序: 1, 4, 3, 2
执行分析:
- 同步:
1,4 - 微任务:
3 - 宏任务:
2
嵌套示例
JavaScript
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
async1();
new Promise(resolve => {
console.log('promise1');
resolve();
}).then(() => {
console.log('promise2');
});
console.log('script end');
// 输出顺序:
// script start
// async1 start
// async2
// promise1
// script end
// async1 end
// promise2
// setTimeout
async/await 执行机制
text
async function foo() {
console.log('a');
await bar();
console.log('b'); // 等同于 Promise.then
}
function bar() {
console.log('c');
}
foo();
console.log('d');
// 输出: a, c, d, b
await后面的代码会放入微任务队列
Node.js 事件循环
Node.js 有 6 个阶段:
text
┌───────────────────────┐
┌─>│ timers │ setTimeout/setInterval
│ └───────────┬───────────┘
│ ┌───────────┴───────────┐
│ │ I/O callbacks │
│ └───────────┬───────────┘
│ ┌───────────┴───────────┐
│ │ idle, prepare │
│ └───────────┬───────────┘
│ ┌───────────┴───────────┐
│ │ poll │ 轮询
│ └───────────┬───────────┘
│ ┌───────────┴───────────┐
│ │ check │ setImmediate
│ └───────────┬───────────┘
│ ┌───────────┴───────────┐
└──┤ close callbacks │
└───────────────────────┘
要点总结
- JavaScript 单线程,事件循环实现异步
- 执行顺序:同步代码 → 微任务 → 宏任务
- 微任务优先于宏任务执行
async/await中 await 后的代码是微任务- Node.js 事件循环有独立的阶段模型
📝 发现内容有误?点击此处直接编辑