事件循环
JavaScript事件循环机制详解
1. 事件循环基础
JavaScript 是单线程语言,事件循环是实现异步非阻塞的核心机制。
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// 输出:1, 4, 3, 2
2. 宏任务与微任务
| 宏任务 | 微任务 |
|---|---|
<script> 整体代码 | Promise.then/catch/finally |
| setTimeout/setInterval | MutationObserver |
| I/O 回调 | queueMicrotask |
| UI 渲染 | process.nextTick(Node.js) |
| setImmediate(Node.js) |
执行顺序
- 执行同步代码(宏任务)
- 清空所有微任务
- 执行一个宏任务
- 重复 2-3
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
3. Node.js 事件循环
timers → pending → idle/prepare → poll → check → close callbacks
// process.nextTick 优先级最高
setImmediate(() => console.log('immediate'));
Promise.resolve().then(() => console.log('promise'));
process.nextTick(() => console.log('nextTick'));
// 输出:nextTick → promise → immediate
4. requestAnimationFrame
// rAF 在渲染前执行,跟随屏幕刷新率
function animate() {
element.style.transform = `translateX(${x}px)`;
requestAnimationFrame(animate);
}