我有代码:
const readStream = fs.createReadStream(readFilename, {
highWaterMark: 10 * 1024
});
const writeStream = fs.createWriteStream(writeFilename, {
highWaterMark: 1 * 1024
});
readStream.pipe(writeStream);
如您所见,两者的缓冲区(highWaterMark)大小不同。读取具有更高的缓冲区,当读取管道写入它确实对写入缓冲区来说太多了。它在内存中保留9 * 1014,在处理完整个负载后,它会调用drain。这很好。
然而。当写入通过writable.write
手动写入时,会返回false
,因此您可以更改读取流以使缓冲区更低(如果这是您想要的)。
我的问题是,因为我直接滚动,无论如何都要听写在可写上的写事件?我唯一可以听到的是之后的排水事件已经过多了。
答案 0 :(得分:1)
一般的回答是“不,因为没有必要”。,但军事程度较低的人会说“ ”,但又会产生另一种后果。。
首先,对于drain
事件在管道流中的含义有误解:
Writable
缓冲区耗尽时会调用它,但这仅是node.js内部缓冲区,而不是通往文件系统的实际管道。pipe
方法实际上在两个流周围都创建了许多侦听器和pause
/ resume
逻辑。Readable
正在监听Writable#drain
事件,以将更多数据推入缓冲区。第二,如前所述-Writable
并没有实现对已写入特定chunk
的任何确认,这仅仅是因为在string
和Buffer
块上,很难说出它们实际上是什么时候写的(在gzip
流的简单情况下,有时甚至不可能将一部分块写到实际磁盘上也是如此)。
有一种方法可以使距离足够近(每个块获得几乎精确的确认):
const {PassThrough} = require("stream");
fs.createReadStream(readFilename, {
highWaterMark: 10 * 1024
})
/* we pipe the readable to a buffer in a passthrough stream */
.pipe(new PassThrough({
highWaterMark: 1024
}))
/* pipe returns the stream we piped to */
/* now we pipe again, but to a stream with no highWaterMark */
.pipe(
new PassThrough({
highWaterMark: 1
})
.on("data", () => {
/* here's your confirmation called just before this chunk is written and after the last one has started to be written */
})
)
/* and there we push to the write stream */
.pipe(
fs.createWriteStream(writeFilename, {
highWaterMark: 1
})
);
当然,这肯定会对性能产生影响,但我不知道它有多大,但是它将使读取方或多或少有效且可写将获得所需的缓冲区-但要有一些额外的CPU和一些微型每个块的延迟。
要由您来测试。
答案 1 :(得分:-2)
是的。您可以收听data
事件:
readStream.on('data', data => console.log(data))