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. 维护两个队列:macroQueue 和 microQueue
  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"
相关推荐
可乐鸡翅yeah_21 分钟前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒33 分钟前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技42 分钟前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
yivifu1 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub
weixin_448290252 小时前
书庐开发实战教学
javascript·css·html
默_笙2 小时前
🛴 从散件到整机:DeepAgents 与 Agent 身上预留的那些"插槽"(前置介绍)
前端·javascript
zhangzeyuaaa2 小时前
深入理解 Ruby 运算符:本质、分类、坑点与重载实战
开发语言·前端·ruby
一木 之林3 小时前
DeepSeek Agent 开发(一)
开发语言·前端·javascript
树下水月4 小时前
Typora破解
linux·服务器·前端
用户5508492902564 小时前
CSS布局实战:从Flex到Grid的完整避坑指南
前端