eventloop js实现
Event Loop 的实现原理
JavaScript 的 Event Loop 是单线程异步编程的核心机制,负责协调调用栈、微任务队列和宏任务队列的执行顺序。以下是其核心实现逻辑:

调用栈(Call Stack)
调用栈用于跟踪当前执行的函数。当一个函数被调用时,会被推入栈顶;执行完毕后从栈顶弹出。如果栈被同步任务阻塞(如无限循环),浏览器会失去响应。

function foo() {
console.log("foo");
}
function bar() {
foo();
}
bar(); // 调用栈顺序: bar -> foo
任务队列(Task Queues)
异步任务被分为两类队列:
- 宏任务队列(Macrotask Queue):包含
setTimeout、setInterval、I/O 操作、UI 渲染等。 - 微任务队列(Microtask Queue):包含
Promise.then、MutationObserver、queueMicrotask。
Event Loop 循环流程
- 执行调用栈中的同步代码,直到栈为空。
- 检查微任务队列,依次执行所有微任务,直到队列清空。
- 渲染页面(如果需要)。
- 从宏任务队列取出一个任务执行,回到步骤 1。
console.log("Start");
setTimeout(() => console.log("Timeout"), 0);
Promise.resolve().then(() => console.log("Promise"));
console.log("End");
// 输出顺序: Start -> End -> Promise -> Timeout
手动模拟简单 Event Loop
以下是一个极简的 Event Loop 模拟实现:
class EventLoop {
constructor() {
this.macroQueue = []; // 宏任务队列
this.microQueue = []; // 微任务队列
}
// 添加宏任务
addMacroTask(task) {
this.macroQueue.push(task);
}
// 添加微任务
addMicroTask(task) {
this.microQueue.push(task);
}
// 启动循环
run() {
while (true) {
// 执行所有微任务
while (this.microQueue.length > 0) {
const task = this.microQueue.shift();
task();
}
// 执行一个宏任务
if (this.macroQueue.length > 0) {
const task = this.macroQueue.shift();
task();
}
}
}
}
// 使用示例
const loop = new EventLoop();
loop.addMacroTask(() => console.log("Macro 1"));
loop.addMicroTask(() => console.log("Micro 1"));
loop.addMacroTask(() => console.log("Macro 2"));
loop.run();
// 输出顺序: Micro 1 -> Macro 1 -> Macro 2
关键注意事项
- 微任务优先级高于宏任务:每次调用栈清空后,会先执行所有微任务。
- 避免阻塞 Event Loop:长时间同步代码会阻塞渲染和任务执行。
- Node.js 差异:Node.js 中
process.nextTick的优先级高于微任务,且宏任务分为多个阶段(如setImmediate)。






