2026年03月27日-Node.js事件循环机制


文档摘要

2026年03月27日-Node.js事件循环机制 Node.js事件循环深度解析 Node.js的异步非阻塞I/O模型是其高性能的核心。深入理解事件循环机制,对于编写高性能Node.js应用至关重要。 事件循环阶段 Node.js事件循环分为6个阶段,按顺序循环执行: Timers阶段:执行setTimeout和setInterval的回调 Pending Callbacks阶段:执行延迟到下一个循环的I/O回调 Idle/Prepare阶段:内部使用 Poll阶段:获取新的I/O事件,执行I/O回调(除了timers、close、setImmediate) Check阶段:执行setImmediate的回调 Close Callbacks阶段:执行socket.

2026年03月27日-Node.js事件循环机制

Node.js事件循环深度解析

Node.js的异步非阻塞I/O模型是其高性能的核心。深入理解事件循环机制,对于编写高性能Node.js应用至关重要。

事件循环阶段

Node.js事件循环分为6个阶段,按顺序循环执行:

  1. Timers阶段:执行setTimeout和setInterval的回调
  2. Pending Callbacks阶段:执行延迟到下一个循环的I/O回调
  3. Idle/Prepare阶段:内部使用
  4. Poll阶段:获取新的I/O事件,执行I/O回调(除了timers、close、setImmediate)
  5. Check阶段:执行setImmediate的回调
  6. Close Callbacks阶段:执行socket.on('close')等关闭回调

执行顺序示例

console.log('1. 开始'); setTimeout(() => { console.log('2. setTimeout'); }, 0); setImmediate(() => { console.log('3. setImmediate'); }); console.log('4. 结束'); // 输出顺序:1, 4, 2/3(顺序不确定), 3/2

微任务与宏任务

微任务(Microtask):优先级高于宏任务,在每个阶段后执行

  • process.nextTick
  • Promise.then/.catch/.finally
  • queueMicrotask

宏任务(Macrotask):按阶段执行

  • setTimeout
  • setInterval
  • setImmediate
  • I/O操作

执行优先级

console.log('开始'); setTimeout(() => console.log('timeout1'), 0); Promise.resolve().then(() => { console.log('promise1'); process.nextTick(() => console.log('nextTick1')); }); process.nextTick(() => { console.log('nextTick2'); Promise.resolve().then(() => console.log('promise2')); }); console.log('结束'); // 输出:开始 -> 结束 -> nextTick2 -> promise1 -> promise2 -> nextTick1 -> timeout1

process.nextTick vs setImmediate

process.nextTick

  • 当前操作完成后立即执行
  • 优先级高于所有微任务
  • 可能导致I/O饥饿
process.nextTick(() => { console.log('nextTick回调'); });

setImmediate

  • Check阶段执行
  • 适合递归调用避免阻塞I/O
setImmediate(() => { console.log('setImmediate回调'); });

异步编程模式

回调函数

const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) { console.error('读取失败:', err); return; } console.log('文件内容:', data); });

Promise链式调用

function readFilePromise(filename) { return new Promise((resolve, reject) => { fs.readFile(filename, 'utf8', (err, data) => { if (err) reject(err); else resolve(data); }); }); } readFilePromise('file.txt') .then(data => console.log(data)) .catch(err => console.error(err));

async/await

const util = require('util'); const readFile = util.promisify(fs.readFile); async function processFile() { try { const data = await readFile('file.txt', 'utf8'); console.log(data); } catch (err) { console.error('错误:', err); } } processFile();

事件驱动架构

EventEmitter核心模式

const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); // 监听事件 myEmitter.on('event', (a, b) => { console.log('事件触发', a, b); setImmediate(() => { console.log('异步处理'); }); }); // 触发事件 myEmitter.emit('event', '参数A', '参数B');

一次性监听器

myEmitter.once('connect', () => { console.log('仅触发一次'); });

错误处理

myEmitter.on('error', (err) => { console.error('错误发生:', err); }); // 如果没有error监听器,错误会导致进程退出 myEmitter.emit('error', new Error('出错了'));

Stream流处理

可读流(Readable)

const fs = require('fs'); const readStream = fs.createReadStream('large_file.txt', { highWaterMark: 1024 * 1024 // 缓冲区大小1MB }); readStream.on('data', (chunk) => { console.log(`读取到 ${chunk.length} 字节`); }); readStream.on('end', () => { console.log('读取完成'); }); readStream.on('error', (err) => { console.error('错误:', err); });

可写流(Writable)

const writeStream = fs.createWriteStream('output.txt'); writeStream.write('第一行\n'); writeStream.write('第二行\n'); writeStream.end();

管道(Pipe)

const readStream = fs.createReadStream('input.txt'); const writeStream = fs.createWriteStream('output.txt'); readStream.pipe(writeStream);

性能优化建议

避免阻塞事件循环

// 错误示例:同步操作阻塞事件循环 const data = fs.readFileSync('large_file.txt'); // 正确示例:异步操作 fs.readFile('large_file.txt', (err, data) => { // 处理数据 });

使用worker_threads处理CPU密集型任务

const { Worker } = require('worker_threads'); function runWorker(data) { return new Promise((resolve, reject) => { const worker = new Worker('./heavy-task.js', { workerData: data }); worker.on('message', resolve); worker.on('error', reject); worker.on('exit', (code) => { if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`)); }); }); }

集群模式利用多核

const cluster = require('cluster'); const os = require('os'); if (cluster.isMaster) { const cpuCount = os.cpus().length; for (let i = 0; i < cpuCount; i++) { cluster.fork(); } cluster.on('exit', (worker) => { console.log(`Worker ${worker.id} died`); cluster.fork(); // 重启worker }); } else { require('./app.js'); // 启动应用 }

内存泄漏排查

常见原因

  1. 未清理的定时器
  2. 全局变量缓存
  3. 事件监听器未移除
  4. 闭包引用

使用heapdump快照

const heapdump = require('heapdump'); // 手动生成快照 heapdump.writeSnapshot('/tmp/heapdump-' + Date.now() + '.heapsnapshot'); // 定期生成快照用于分析 setInterval(() => { heapdump.writeSnapshot('./snapshots/heap-' + Date.now() + '.heapsnapshot'); }, 60000); // 每分钟

使用v8-profiler监控

const v8Profiler = require('v8-profiler-next'); v8Profiler.startProfiling('CPU profile'); // ... 运行一段时间 const profile = v8Profiler.stopProfiling('CPU profile'); profile.export((err, result) => { fs.writeFileSync('profile.cpuprofile', result); profile.delete(); });

Node.js事件循环机制是实现高性能异步编程的基础。理解其工作原理,合理使用异步API,避免阻塞操作,才能充分发挥Node.js的并发处理能力。结合性能监控工具,持续优化应用性能,构建高效稳定的Node.js应用。


发布者: 作者: 转发
评论区 (0)
U