Node\.js 事件循环核心知识点总结

Node.js 事件循环核心知识点总结

一、核心概述

Node.js 基于单线程、非阻塞、异步 I/O模型运行,**事件循环(Event Loop)**是其实现异步调度的核心,负责统筹所有异步任务的执行顺序,避免线程阻塞,实现高并发能力。

事件循环会按固定阶段循环执行,每个阶段拥有独立回调队列,清空当前阶段队列后,才会进入下一阶段,且每个阶段切换前会优先清空所有微任务

二、事件循环完整执行阶段(从上至下为执行顺序)

完整6阶段顺序:timers → pending callbacks → idle/prepare → poll → check → close callbacks

1. Timers 阶段(定时器阶段)

  • 执行任务setTimeout\(\)setInterval\(\) 回调函数

  • 核心特点:设定的时间为最小延迟,非精确执行时间,需等待当前阶段空闲后执行

2. Pending callbacks 阶段(延迟回调阶段)

  • 执行任务:上一轮循环遗留的 I/O 错误回调、系统级回调

  • 核心特点:Node 内部底层处理,日常业务开发无需关注

3. Idle/Prepare 阶段(空闲预备阶段)

  • 核心特点:仅 Node 内部调度使用,开发者无业务交互

4. Poll 阶段(轮询阶段,核心重点)

  • 执行任务:普通文件、网络等** I/O 异步回调**

  • 核心逻辑

    1. 队列有任务:同步清空当前所有 I/O 回调

    2. 队列为空:若存在 setImmediate,直接进入 Check 阶段;若有定时器到期,回到 Timers 阶段;无任务则阻塞等待新事件

5. Check 阶段(检查阶段)

  • 执行任务:专属执行 setImmediate\(\) 回调

  • 核心特点:Poll 阶段结束后立即执行,优先级高于定时器(特定场景)

6. Close callbacks 阶段(关闭回调阶段)

  • 执行任务:关闭类回调,如 socket\.close\(\)stream\.on\(\&\#39;close\&\#39;\)

  • 核心特点:一轮循环的收尾阶段,处理资源释放回调

三、任务分类与执行优先级

Node 异步任务分为 微任务(高优先级)宏任务(低优先级),微任务执行优先级高于所有宏任务。

1. 微任务队列(优先执行)

优先级:process\.nextTick > 原生 Promise.then/catch/finally

  • process\.nextTick:Node 独有微任务,全局最高异步优先级

  • Promise 微任务:常规异步微任务,优先级次于 nextTick

  • 规则:每一个事件循环阶段切换前,必须清空所有微任务

2. 宏任务队列(按阶段执行)

执行顺序对应事件循环阶段:Timers 宏任务 → Poll I/O 宏任务 → Check 宏任务 → Close 宏任务

  • Timers 宏任务:setTimeoutsetInterval

  • Poll 宏任务:普通文件、网络 I/O 回调

  • Check 宏任务:setImmediate

3. 终极执行顺序(必记)

同步代码 > process.nextTick > Promise 微任务 > setTimeout/setInterval > setImmediate

四、重点 API 特殊场景

setTimeout(0) vs setImmediate 区别

  1. 全局主代码中:执行结果随机,取决于 Node 进程启动耗时,启动快则定时器先执行,反之 setImmediate 先执行

  2. I/O 回调内部setImmediate 必定优先执行(I/O 回调属于 Poll 阶段,结束后直接进入 Check 阶段,跳过 Timers 阶段)

五、经典代码示例与执行解析

示例代码

console.log('同步代码1');

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

setImmediate(() => {
  console.log('setImmediate');
});

Promise.resolve().then(() => {
  console.log('Promise.then 微任务');
});

process.nextTick(() => {
  console.log('process.nextTick');
});

console.log('同步代码2');

执行输出结果

同步代码1
同步代码2
process.nextTick
Promise.then 微任务
setTimeout 0ms
setImmediate

执行步骤拆解

  1. 执行所有同步代码,打印同步内容

  2. 清空微任务队列:优先执行 process\.nextTick,再执行 Promise 微任务

  3. 进入事件循环:Timers 阶段执行 setTimeout 回调

  4. 流转到 Check 阶段,执行 setImmediate 回调

六、核心总结

  • 事件循环核心阶段:Timers、Poll、Check 为业务核心阶段,其余为底层内部阶段

  • 微任务优先级永远高于宏任务,nextTick 是最高优先级异步任务

  • 定时器是最小延迟,非精准定时,受事件循环调度影响

  • I/O 回调中 setImmediate 永远快于 0ms 定时器


本文由萧兮的博客原创发布,欢迎转载,转载务必保留原文链接。

萧兮的博客https://www.20010515.xyz · 原文:https://www.20010515.xyz/posts/019e4ece-afe7-7cb0-a98b-a32478890169