我有这个代码:
const { Writable } = require('stream')
let writable = new Writable({ highWaterMark: 10 })
writable._write = (chunk, encoding, cb) => {
process.stdout.write(chunk)
}
function writeData(iterations, writer, data, encoding, cb) {
(function write() {
if (!iterations--) return cb()
if (!writer.write(data, encoding)) {
console.log(` <wait>: highWaterMark reached`)
writer.once('drain', write) // same result when I comment this line
}
})()
}
writeData(4, writable, 'String longer than highWaterMark', 'utf8', () => console.log('Done'))
当我评论检查 'drain'
事件以再次写入的代码时,我得到了相同的结果。
String longer than highWaterMark <wait> highWaterMark reached
看起来 Node 会自动执行此操作,那么为什么我们自己手动监听 'drain'
事件呢?
最佳答案
如果您不等待 drain
事件, Node 将继续缓冲您的 block ,直到出现最大内存使用量。
一旦达到 highWaterMark
阈值, Node 将尝试刷新缓冲区并写入磁盘,但这发生在事件循环的下一个滴答声中,所以如果你不等待(你继续写),这永远不会发生。
I have the same result when I comment the code that check for a 'drain' event to write again.
你有相同的最终结果,因为你没有多次调用 .write
(足以达到内存限制)。但是,如果您对正在写入的文件执行 tail -f
,您将看到在您的进程退出之前没有写入任何内容,或者在这种情况下您的 writeData
函数结束。但是如果您尊重排水管,您会看到文件正在写入(highWaterMark
字节),而您的进程仍在运行。
无需等待,您的代码将阻塞事件循环,直到文件完全写入,这与使用 fs.writeFileSync
几乎相同。因此,如果您在具有数千个并发请求的服务器上执行此操作,您就会理解等待耗尽事件发生的重要性。
你可以检查这个问题,在那里你会看到 .write
是如何进行缓冲的,如果你不等待 drain 事件会发生什么:why does attempting to write large a large file cause js heap to run out of memory
It seems like Node does that automatically, so why bother our-self listening for 'drain' event manually ?
当您使用 .pipe
而不是 .write
时,Node 会为您处理它
const read = fs.createReadStream('/tmp/file.txt');
const write = fs.createWriteStream('/tmp/copy.txt');
read.pipe(write); // You don't have to handle `drain`
关于javascript - Node : Does a writable stream wait for the drain event automatically before writing again?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51063278/