Node.js事件循环中pending callbacks与poll阶段的差异解析
区分Node.js事件循环的pending callbacks与poll阶段I/O回调
核心差异
pending callbacks阶段负责处理延迟到下一次循环迭代的I/O回调,这类回调多是系统级操作的遗留回调;poll阶段则是处理新产生的I/O事件回调,也是绝大多数常规异步I/O回调的执行场所。
示例1:pending callbacks阶段的场景(TCP连接错误回调)
const net = require('net'); // 尝试连接一个不存在的本地端口 const socket = new net.Socket(); socket.connect(8123, 'localhost', () => { console.log('连接成功'); }); socket.on('error', (err) => { console.log('触发error回调:', err.message); }); // 同步代码优先执行 console.log('同步代码执行');
执行流程说明:
- 同步代码先运行,输出
同步代码执行。 - TCP连接尝试失败时,对应的错误回调不会立即在当前循环的poll阶段处理,而是被延迟到下一次循环的pending callbacks阶段执行。
- 事件循环流转到pending callbacks阶段时,才会触发
error回调,输出类似触发error回调:connect ECONNREFUSED 127.0.0.1:8123的内容。
示例2:poll阶段的场景(文件读取回调)
const fs = require('fs'); // 异步读取本地文件 fs.readFile('./example.txt', 'utf8', (err, data) => { if (err) throw err; console.log('文件读取完成:', data); }); // 同步代码优先执行 console.log('同步代码执行');
执行流程说明:
- 同步代码先运行,输出
同步代码执行。 - Node.js在poll阶段会等待文件I/O操作完成,一旦读取完成,对应的回调会立即在当前poll阶段执行,输出
文件读取完成:[文件内容]。
对比示例:两个阶段的执行顺序
const net = require('net'); const fs = require('fs'); // 触发pending callbacks的回调 const socket = new net.Socket(); socket.connect(8123, 'localhost'); socket.on('error', () => console.log('pending callbacks阶段:TCP错误回调')); // 触发poll阶段的回调 fs.readFile('./example.txt', 'utf8', () => console.log('poll阶段:文件读取回调')); console.log('同步代码执行');
预期输出顺序(假设example.txt存在且读取无异常):
同步代码执行 poll阶段:文件读取回调 pending callbacks阶段:TCP错误回调
原因:
poll阶段会优先处理新产生的I/O事件回调,等poll阶段的任务处理完后,事件循环才会进入pending callbacks阶段处理延迟的遗留回调。
内容的提问来源于stack exchange,提问作者MaximPro
相关产品推荐
相关产品推荐

