你了解 Node.js 的事件循环机制吗?

Node.js 的事件循环机制是其高效处理异步任务的核心。它分为六个阶段,每个阶段负责不同的任务队列,确保高并发请求的响应。

Node.js 中等 事件循环 异步 异步处理

事件循环是 Node.js 运行时环境的核心机制,用于处理异步任务和 I/O 操作,使得单线程 Node.js 能高效处理高并发请求。基于 libuv 库实现的事件循环由六个阶段组成,并按照顺序反复运行,每个阶段处理特定任务。以下是事件循环的工作原理概述和阶段的详细描述:

工作原理概述

Node.js 事件循环遵循事件驱动模型:

  • 初始时,启动事件循环并执行所有同步任务。
  • 非阻塞 I/O 任务(如文件读写的异步操作或定时器)通过操作系统或线程池处理。
  • 完成后,对应回调函数被加入事件队列,等待事件循环处理。
  • 主线程空闲时循环执行以下六个阶段。

六个阶段详解

事件循环分为固定顺序的六个阶段,每个阶段有其特定任务队列:

  1. Timers 阶段:执行 setTimeoutsetInterval 中的回调函数,处理定时器到期的事件。
  2. Pending I/O Callbacks 阶段:执行上一轮循环中未完成的 I/O 回调事件,包括如 TCP 错误回调等系统级任务。
  3. Idle/Prepare 阶段:用于 Node.js 内部处理任务,如垃圾回收或资源准备,不暴露给外部代码。
  4. Poll 阶段:核心 I/O 处理阶段:
    • 检查新的 I/O 事件,执行读写文件或网络请求的回调。
    • 如果没有任务,等待新事件加入或跳转到下一阶段。
    • 遇到 setImmediate 回调时提前结束此阶段。
  5. Check 阶段:处理 setImmediate 设置的回调函数,通常在 I/O 操作完成后执行。
  6. Close Callbacks 阶段:执行关闭相关事件的回调,如 socket.on('close', ...) 或文件描述符关闭。

典型运行流程

在一个事件循环周期中:

  • 任务先进入初始事件队列,事件循环按阶段顺序依次处理。
  • 各阶段按先入先出原则执行队列回调。
  • Poll 阶段是关键:如果没有新 I/O 事件(队列为空),检查已存在未完成的阶段任务,决定是阻塞等待、处理回拨还是前进。
  • 在每一轮中运行当前队列直到空(或数量、时间限制),然后移到下一阶段。

通过这些机制,Node.js 能够协调异步任务,确保高吞吐量和低延迟,非常适合实时应用场景。