好的,继续你的前端高频题训练。
✅ 第 37 题:深入理解事件循环(Event Loop)、微任务、宏任务(详细 + 难点 + 易错点)
这题在前端面试中属于 顶级高频题,并且往往是笔试 + 面试双重考。
我会讲:
- 原理(你能向面试官讲清楚的那种)
- 浏览器与 Node 的区别
- 经典必考输出题
- 容易被坑的知识点
- 速记卡片
一、什么是事件循环(Event Loop)?
一句话:
JS 是单线程的,为了不阻塞任务执行,就通过事件循环机制来调度异步任务。
事件循环主要处理两类任务:
- 宏任务(Macro task)
- 微任务(Micro task)
二、宏任务 vs 微任务(非常关键)
✔ 宏任务(Macro task)
每一轮事件循环执行 一个 宏任务。
常见宏任务:
setTimeoutsetIntervalsetImmediate(Node)I/OUI 渲染- 整个 script 一次整体执行(没错,
script也是宏任务)
✔ 微任务(Micro task)
当一个宏任务执行结束后,会立即清空所有微任务队列。
常见微任务:
Promise.then / catch / finallyMutationObserverqueueMicrotask- Node 中还有
process.nextTick(优先级最高)
三、事件循环执行顺序(面试官最爱问)
一句话版流程:
执行宏任务
↓
执行期间遇到微任务 → 放入微任务队列
↓
当前宏任务执行完 → 立即清空所有微任务
↓
进入下一轮宏任务
四、浏览器 vs Node 的区别(高频点)
浏览器事件循环:
宏任务 → 微任务 → 渲染 → 下一轮宏任务
Node 事件循环更复杂,有六个阶段:
- timers
- pending callbacks
- idle, prepare
- poll
- check
- close callbacks
以及:
- process.nextTick(优先级最高)
- 然后才是微任务(Promise)
五、经典必考题(你必须会默写)
📌 例题 1:Promise vs setTimeout
javascript
console.log(1);
setTimeout(() => console.log(2));
Promise.resolve().then(() => console.log(3));
console.log(4);
执行顺序:
1 → 4 → 3 → 2
解析:
- 1、4:同步
- 3:微任务
- 2:宏任务
📌 例题 2:嵌套微任务
javascript
Promise.resolve().then(() => {
console.log('micro 1');
Promise.resolve().then(() => console.log('micro 2'));
});
console.log('sync');
输出:
bash
sync
micro 1
micro 2
原因:
微任务永远全部清空。
📌 例题 3:setTimeout vs Promise 再套 setTimeout
javascript
setTimeout(() => console.log(1));
Promise.resolve().then(() => {
console.log(2);
setTimeout(() => console.log(3));
});
console.log(4);
顺序:
4 → 2 → 1 → 3
解释:
- 4:同步
- 2:微任务
- 1:第一轮的宏任务
- 3:Promise 里的 setTimeout → 第二轮宏任务
📌 例题 4:Node 特性 --- process.nextTick
javascript
console.log(1);
setTimeout(() => console.log(2));
Promise.resolve().then(() => console.log(3));
process.nextTick(() => console.log(4));
console.log(5);
Node 输出:
arduino
1
5
4 ← process.nextTick 优先级最高
3 ← 微任务
2 ← 宏任务
六、面试官深入追问(你必须会答)
❓为什么 Promise.then 会比 setTimeout 先执行?
因为 Promise 是微任务,而 setTimeout 是宏任务。
每一轮事件循环结束会立即执行所有微任务 → 永远先于宏任务。
❓微任务可以产生新的微任务吗?
可以,而且会继续在当前 microtask queue 中执行。
❓浏览器什么时候渲染?
一次事件循环中:
宏任务 → 微任务 → (若需要则渲染)
渲染只在两次宏任务之间,不会打断微任务执行。
七、速记卡片(给你复习)
🟦 事件循环 --- 速记卡片
🟣 宏任务(一次执行一个)
- script
- setTimeout
- setInterval
- UI 渲染
- I/O
🔵 微任务(每轮执行完宏任务就清空)
- Promise.then
- queueMicrotask
- MutationObserver
- (Node) process.nextTick(优先级最高)
🟢 执行顺序
宏任务
→ 执行所有微任务
→ 渲染(浏览器)
→ 下一轮宏任务
🔴 Node 特殊优先级
arduino
process.nextTick > Promise microtask > macrotask
要继续第 38 题吗?
下一题是:
👉 第 38 题:浏览器渲染流程(重排 Reflow、重绘 Repaint、合成 Compositing)
继续吗?