javascript - Node : Does a writable stream wait for the drain event automatically before writing again?

标签 javascript node.js

我有这个代码:

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/

相关文章:

javascript - 通过变量 angularjs 选择我范围内的一个项目

javascript - height 在 angularJS 指令内返回 0

javascript - 环回自动迁移与自动更新

node.js - 如何订购一个 firebase 集合,然后向每个文档写入一些内容?

javascript - trim 来自 stdin 的输入

javascript - 带钩子(Hook)的 React 函数组件与类组件

javascript - 给定键列表,如何将对象的值作为数组获取?

javascript - 启用分页时如何从 JSON api 获取所有数据?

javascript - 在 Node.js 中,如何存储主应用程序中模块函数的回调数据?

javascript - Promise 在 Node module.exports 中返回未定义