Node.js中stream.Readable的'readable'事件触发时机及代码运行疑问
为什么Node.js Readable流没手动调用
_read()也能触发readable事件? 先贴一下你的代码方便对照:
const stream = require('stream') const readable = new stream.Readable({ encoding: 'utf8', highWaterMark: 16000, objectMode: false }) const news = [ 'News #1', 'News #2', 'News #3' ] readable._read = () => { if(news.length) { return readable.push(news.shift() + '\n') } return readable.push(null) } readable.on('readable', () => { let data = readable.read() if(data) { process.stdout.write(data) } }) readable.on('end', () => { console.log('No more feed') })
嘿,这个问题问得特别好——刚接触Node.js流的时候,确实会被这种“自动干活”的逻辑搞懵,我当初学的时候也卡过这儿😉
核心原因其实是Node.js的Readable流会自动管理数据的填充流程,不需要你手动去调用_read()或者推送数据,具体来说是这几个关键点:
1. 监听readable事件等于给流发了“消费信号”
当你给流绑定readable事件回调的时候,就相当于告诉流:“我准备好接收数据啦,快把数据弄过来”。此时Node.js的流内部机制会自动触发你重写的_read()方法,开始往缓冲区里填充数据。
2. _read()是流的“数据供应入口”
你重写的_read()方法是流的数据源逻辑——流每次需要数据的时候(比如缓冲区空了、刚有消费者监听),就会自动调用这个方法,然后你通过push()把数据放到流的内部缓冲区里。
当你push(null)的时候,就是在告诉流:“没数据了,我要结束了”,这时候流后续就会触发end事件。
3. 整个流程的自动运转逻辑
咱们把你的代码走一遍流程就清楚了:
- 初始化
readable流,并且定义了_read()的数据源逻辑; - 你绑定了
readable事件,流检测到有消费者,立刻调用_read(); _read()把News #1推到缓冲区,此时缓冲区有数据了,就触发readable事件;- 你在回调里用
read()把数据读出来输出到控制台; - 输出后缓冲区空了,流会再次调用
_read(),继续推News #2,重复上面的步骤; - 直到
news数组为空,push(null),流触发end事件,打印“No more feed”。
简单来说,Node.js的Readable流就是设计成“自动按需填充数据”的模式,开发者只需要负责提供数据源(写好_read())和处理数据(监听事件),剩下的驱动流程交给流内部去做就行啦。
内容的提问来源于stack exchange,提问作者user278077
相关产品推荐
相关产品推荐

