Skip to Content
Nextra 4.0 is released 🎉
Plan第 2 周 · Event Loop 与浏览器任务调度

🎯 本周总目标

你要能够在脑中精确排出任何一段异步代码的执行顺序。

✅ 本周达标标准

  • 能说清:为什么 Promise 比 setTimeout 快
  • 能区分:宏任务 / 微任务 / UI 渲染时机
  • 能解释:requestAnimationFrame 的真实执行位置
  • 能画出:完整 Event Loop 时序图
  • 能手写:最小 Event Loop 执行器

一、Event Loop 的整体模型

JS 是 单线程执行 + 事件循环驱动 的模型。

1️⃣ 核心组成

Call Stack(调用栈) Task Queue(任务队列) ├─ Macro Task Queue(宏任务) └─ Micro Task Queue(微任务) UI Render Queue(渲染队列)

核心规则:先执行当前栈 → 再清空微任务 → 再取一个宏任务 → 再渲染


二、宏任务 vs 微任务

✅ 宏任务(Macro Task)

  • script
  • setTimeout
  • setInterval
  • setImmediate(Node)
  • MessageChannel
  • I/O

✅ 微任务(Micro Task)

  • Promise.then / catch / finally
  • MutationObserver
  • queueMicrotask

三、执行顺序“四步循环法则”

1️⃣ 执行一个宏任务(最开始是 script) 2️⃣ 清空所有微任务 3️⃣ 若需要,进行一次 UI 渲染 4️⃣ 执行下一个宏任务

四、基础顺序推导题

console.log(1); setTimeout(() => { console.log(2); }, 0); Promise.resolve().then(() => { console.log(3); }); console.log(4);

✅ 正确输出:

1 4 3 2

推导过程:

  1. 执行主线程:1、4
  2. 微任务队列:3
  3. 宏任务队列:2

五、Promise 嵌套地狱顺序题(分水岭)

console.log(1); setTimeout(() => { console.log(2); Promise.resolve().then(() => console.log(3)); }, 0); Promise.resolve().then(() => { console.log(4); setTimeout(() => console.log(5), 0); }); console.log(6);

✅ 正确输出:

1 6 4 2 3 5

六、requestAnimationFrame 的真实位置

setTimeout(() => console.log('timeout')); requestAnimationFrame(() => console.log('raf')); Promise.resolve().then(() => console.log('promise'));

✅ 一般浏览器行为顺序:

promise raf timeout

说明:rAF 会在 一次 UI 重绘前执行


七、Node.js Event Loop 执行模型(简版)

timers pending callbacks poll check close callbacks microtasks: - process.nextTick - Promise.then

✅ 关键结论:

  • Node 的微任务优先级高于定时器
  • process.nextTick > Promise.then

八、工程级实战:手写最小 Event Loop

class MiniEventLoop { macroQueue = []; microQueue = []; addMacro(fn) { this.macroQueue.push(fn); } addMicro(fn) { this.microQueue.push(fn); } run() { while (this.macroQueue.length) { const macroTask = this.macroQueue.shift(); macroTask(); while (this.microQueue.length) { const microTask = this.microQueue.shift(); microTask(); } } } }

✅ 实战目标:

你要亲眼看到:为什么微任务一定比下一个宏任务先执行


九、真实业务中的 Event Loop 陷阱

✅ 高频线上问题场景:

  • Promise 里的 setState 顺序错乱
  • setTimeout 延迟抖动
  • rAF 中读写 DOM 触发布局抖动
  • 微任务过多导致页面“假死”

✅ 本周 CheckList

  • 能背出完整 Event Loop 执行顺序
  • 能推导至少 5 道 Promise + 定时器 混合题
  • 能解释 rAF 一定发生在渲染之前
  • 能画出浏览器任务循环流程图
  • 已完成 Mini EventLoop 手写版

🚀 下周预告:第 3 周 · 浏览器渲染全流程

  • HTML → DOM 构建
  • CSS → CSSOM
  • Render Tree
  • Layout / Paint / Composite
  • GPU 加速与合成层

进入第 3 周,你将真正理解:为什么页面会卡,卡在了哪里。

最近更新:12/9/2025, 2:17:57 AM