14、✅ 手写 Event Loop 模拟器(理解微任务 / 宏任务调度)

🎯 一、为什么要手写 Event Loop?

  • 大厂面试必问:async/await、Promise、setTimeout 混合输出顺序
  • 源码能力提升:搞懂浏览器/Node.js 的任务调度机制
  • 理解 JS 单线程异步执行本质,为后续自己写任务队列打下基础

🧠 二、Event Loop 核心概念速查

术语 解释
Call Stack 调用栈,JS 执行同步任务的地方
Macro Task 宏任务,如 setTimeout/setInterval/I/O
Micro Task 微任务,如 Promise.then/MutationObserver
Event Loop 事件循环,调度所有任务的"引擎"
  • 执行顺序:主线程同步任务 → 微任务队列 → 宏任务队列
  • 每次执行完一个宏任务后,立即清空所有微任务

🔍 三、常考面试题(输出顺序)

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

输出顺序? 1、4、3、2


✍️ 四、核心思想:模拟微/宏任务队列

  1. 维护两个队列:macroQueuemicroQueue
  2. 每次执行一个 macro 后,依次执行 microQueue 直到清空
  3. 采用递归或循环驱动任务调度

📦 五、简易 Event Loop 模拟器实现

kotlin 复制代码
class EventLoop {
  constructor() {
    this.macroQueue = [];
    this.microQueue = [];
    this.running = false;
  }

  // 加入宏任务
  setMacroTask(fn) {
    this.macroQueue.push(fn);
    this.run();
  }

  // 加入微任务
  setMicroTask(fn) {
    this.microQueue.push(fn);
    this.run();
  }

  run() {
    if (this.running) return;
    this.running = true;

    while (this.macroQueue.length > 0) {
      // 执行一个宏任务
      const macro = this.macroQueue.shift();
      macro();

      // 清空微任务队列
      while (this.microQueue.length > 0) {
        const micro = this.microQueue.shift();
        micro();
      }
    }

    this.running = false;
  }
}

✅ 六、使用示例(验证调度顺序)

arduino 复制代码
const loop = new EventLoop();

console.log(1);

loop.setMacroTask(() => {
  console.log(2);
});

loop.setMicroTask(() => {
  console.log(3);
});

console.log(4);

// 输出:1 4 3 2

🔁 七、进阶模拟 async/await

async/await 本质就是自动拆分为同步 + 微任务

javascript 复制代码
async function test() {
  console.log('a');
  await Promise.resolve();
  console.log('b');
}
test();
console.log('c');
// 输出:a c b
  • await 前为同步,await 后回到微任务

❗ 八、面试陷阱总结

题型 易错点
setTimeout + Promise 谁先输出? Promise 微任务先于 setTimeout 宏任务
多重微任务 一次性全部执行,直到清空 microQueue
多层嵌套 推理需模拟"每次大循环后立即清 micro"
相关推荐
灵感__idea7 小时前
Hello 算法:贪心的世界
前端·javascript·算法
GreenTea9 小时前
一文搞懂Harness Engineering与Meta-Harness
前端·人工智能·后端
killerbasd10 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
吴声子夜歌10 小时前
ES6——二进制数组详解
前端·ecmascript·es6
码事漫谈11 小时前
手把手带你部署本地模型,让你Token自由(小白专属)
前端·后端
ZC跨境爬虫11 小时前
【爬虫实战对比】Requests vs Scrapy 笔趣阁小说爬虫,从单线程到高效并发的全方位升级
前端·爬虫·scrapy·html
爱上好庆祝11 小时前
svg图片
前端·css·学习·html·css3
橘子编程11 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
王夏奇11 小时前
python中的__all__ 具体用法
java·前端·python
叫我一声阿雷吧12 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint