当前位置:首页 > JavaScript

js实现eventloop

2026-02-01 13:49:30JavaScript

Event Loop 的基本概念

Event Loop 是 JavaScript 运行时环境的核心机制,用于处理异步任务和执行顺序。它确保非阻塞 I/O 操作能够高效执行,同时保持单线程的特性。

调用栈(Call Stack)

调用栈是 JavaScript 执行同步代码的地方。函数调用会被压入栈中,执行完毕后弹出。如果栈中出现长时间运行的任务,会导致阻塞。

function foo() {
  console.log('foo');
}
function bar() {
  foo();
  console.log('bar');
}
bar();
// 输出顺序: foo -> bar

任务队列(Task Queue)

异步操作(如 setTimeoutsetInterval、I/O 回调)完成后,会将回调函数放入任务队列。Event Loop 在调用栈为空时,从任务队列中取出任务执行。

console.log('Start');
setTimeout(() => console.log('Timeout'), 0);
console.log('End');
// 输出顺序: Start -> End -> Timeout

微任务队列(Microtask Queue)

微任务队列优先级高于任务队列,通常包括 Promise 的回调、MutationObserver 等。每次调用栈清空后,Event Loop 会先处理所有微任务,再处理任务队列。

console.log('Start');
Promise.resolve().then(() => console.log('Promise'));
setTimeout(() => console.log('Timeout'), 0);
console.log('End');
// 输出顺序: Start -> End -> Promise -> Timeout

Event Loop 的执行流程

  1. 执行同步代码,填充调用栈。
  2. 遇到异步任务时,将回调注册到对应队列(宏任务或微任务)。
  3. 调用栈清空后,检查微任务队列并执行所有微任务。
  4. 执行一个宏任务(如 setTimeout 回调)。
  5. 重复步骤 3-4,直到所有队列为空。

代码示例分析

console.log('Script start');

setTimeout(() => {
  console.log('setTimeout');
}, 0);

Promise.resolve()
  .then(() => {
    console.log('Promise 1');
  })
  .then(() => {
    console.log('Promise 2');
  });

console.log('Script end');

输出顺序:

  1. Script start
  2. Script end
  3. Promise 1
  4. Promise 2
  5. setTimeout

常见异步操作分类

  • 宏任务(Macrotasks): setTimeout, setInterval, I/O, UI rendering
  • 微任务(Microtasks): Promise, process.nextTick (Node.js), MutationObserver

Node.js 中的 Event Loop

Node.js 的 Event Loop 分为多个阶段,每个阶段处理特定类型的任务:

  1. Timers: 执行 setTimeoutsetInterval 回调。
  2. I/O Callbacks: 执行大多数 I/O 相关的回调。
  3. Idle/Prepare: 内部使用。
  4. Poll: 检索新的 I/O 事件。
  5. Check: 执行 setImmediate 回调。
  6. Close Callbacks: 执行关闭事件的回调(如 socket.on('close'))。
setImmediate(() => console.log('setImmediate'));
setTimeout(() => console.log('setTimeout'), 0);
// 输出顺序可能交替,取决于上下文

避免阻塞 Event Loop

长时间运行的同步代码会阻塞 Event Loop,导致异步任务无法及时处理。解决方案包括:

js实现eventloop

  • 将计算密集型任务拆分为小块,使用 setTimeoutsetImmediate 分步执行。
  • 使用 Web Workers 或子进程(Node.js)处理耗时任务。
// 错误示例:阻塞 Event Loop
for (let i = 0; i < 1e9; i++) { /* 长时间运算 */ }

// 改进:分块执行
function chunkedTask(start, end) {
  if (start >= end) return;
  setTimeout(() => {
    for (let i = start; i < Math.min(start + 1e6, end); i++) { /* 处理小块 */ }
    chunkedTask(start + 1e6, end);
  }, 0);
}

总结

Event Loop 通过调用栈、任务队列和微任务队列的协作,实现了 JavaScript 的异步非阻塞执行。理解其运行机制有助于编写高效的异步代码,避免常见性能问题。

标签: jseventloop
分享给朋友:

相关文章

js实现验证码

js实现验证码

使用Canvas生成图形验证码 在HTML中创建一个Canvas元素用于绘制验证码。通过JavaScript随机生成数字或字母组合,并添加干扰线、噪点等干扰元素增强安全性。 <canvas i…

js实现继承

js实现继承

原型链继承 通过将子类的原型指向父类的实例实现继承。子类实例可以访问父类原型上的属性和方法。 function Parent() { this.name = 'parent'; } Parent…

js实现图片轮播

js实现图片轮播

实现基础图片轮播 使用HTML、CSS和JavaScript创建一个简单的图片轮播。HTML部分定义轮播容器和图片,CSS设置样式和动画效果,JavaScript处理轮播逻辑。 <div cl…

js实现图片预览

js实现图片预览

使用FileReader API实现图片预览 通过FileReader对象读取用户选择的图片文件并显示预览: const input = document.getElementById('image…

js实现报表

js实现报表

使用JavaScript实现报表 在JavaScript中实现报表功能可以通过多种方式完成,常见的方法包括使用原生JavaScript、第三方库(如Chart.js、D3.js)或结合后端数据渲染。以…

js实现吸色

js实现吸色

使用Canvas实现吸色功能 通过Canvas的getImageData方法获取像素颜色数据。创建一个Canvas元素,将目标图像绘制到Canvas上,通过鼠标事件获取坐标对应的颜色值。 const…