我正在阅读流文档,并在https://nodejs.org/api/stream.html#stream_buffering上寻找有关流的缓冲行为描述
当通过管道传递到多个输出(因为不同的输出具有不同的消耗速度)时,文档似乎没有提到inputStream缓冲区(或多个缓冲区?)会发生什么情况:
当通过管道传输多个输出时,readystream是否为每个输出保留一个专用缓冲区?
消耗时输出会保持相同的速度还是更快结束?
const input = fs.createReadStream('img.jpg');
const target1 = input.pipe(fs.createWriteStream('target1.jpg'));
const target2 = input.pipe(fs.createWriteStream('target2.jpg'));
答案 0 :(得分:4)
TL; DR:简短的答案是-较慢的目标流控制流量。
所以首先让我们看看在读取方面会发生什么。
const input = fs.createReadStream('img.jpg');
实例化输入流时,它将在暂停模式下创建并计划读取(没有同步读取,因此它尚无法访问文件)。流中的highWaterMark
设置为16384
之类的内容,当前缓冲区为0字节。
const target1 = input.pipe(fs.createWriteStream('target1.jpg'));
const target2 = input.pipe(fs.createWriteStream('target2.jpg'));
现在,当您将其实际传输到可写流时,可以通过在pipe method implementation - see the source中添加on('data')
事件处理程序来设置流模式。
完成此操作后,我假定不再有程序要运行,因此节点开始实际读取并在上面的处理程序中运行计划的代码,该处理程序将简单地写入所有通过的数据。
当任何目标要写入的数据多于其highWaterMark
时,就会发生流控制,这导致了write
操作返回false
。然后,calling pause here in the code停止读取。在此上方的两行中,您会看到state.awaitDrain递增。
现在,读取的流再次为paused
,可写的流将字节写入磁盘-在某些时候,缓冲区级别再次低于highWaterMark
。此时,将触发executes this line事件drain
,并在所有等待的排水口被调用之后,恢复流程。通过检查递减的awaitDrain
属性是否已达到零来完成此操作,这意味着已调用所有等待的消耗事件。
在上述情况下,两个流中较快的流可能在写入时返回虚假值,但肯定会首先消耗虚假值。如果不是awaitDrain
,则更快的流将恢复数据流,这将导致两者中较慢的缓冲区溢出。