如何在Node.js中使用stream.Writable的drain事件 [英] How to use drain event of stream.Writable in Node.js

查看:15
本文介绍了如何在Node.js中使用stream.Writable的drain事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Node.js 中,我使用 fs.createWriteStream 方法将数据附加到本地文件.在 Node 文档中,他们在使用 fs.createWriteStream 时提到了 drain 事件,但我不明白.

In Node.js I'm using the fs.createWriteStream method to append data to a local file. In the Node documentation they mention the drain event when using fs.createWriteStream, but I don't understand it.

var stream = fs.createWriteStream('fileName.txt');
var result = stream.write(data);

在上面的代码中,如何使用drain事件?下面的事件使用正确吗?

In the code above, how can I use the drain event? Is the event used properly below?

var data = 'this is my data';
if (!streamExists) {
  var stream = fs.createWriteStream('fileName.txt');
}

var result = stream.write(data);
if (!result) {
  stream.once('drain', function() {
    stream.write(data);
  });
}

推荐答案

drain 事件用于可写流的内部缓冲区已被清空.

The drain event is for when a writable stream's internal buffer has been emptied.

只有当内部缓冲区的大小超过其 highWaterMark 属性时才会发生这种情况,该属性是可写流的内部缓冲区中可以存储的最大数据字节数,直到它停止从数据来源.

This can only happen when the size of the internal buffer once exceeded its highWaterMark property, which is the maximum bytes of data that can be stored inside a writable stream's internal buffer until it stops reading from the data source.

造成这种情况的原因可能是设置涉及从一个流读取数据源的速度比写入另一个资源的速度快.例如,取两个流:

The cause of something like this can be due to setups that involve reading a data source from one stream faster than it can be written to another resource. For example, take two streams:

var fs = require('fs');

var read = fs.createReadStream('./read');
var write = fs.createWriteStream('./write');

现在假设文件 read 位于 SSD 上,可以以 500MB/s 的速度读取,write 位于只能以 150MB/写入的 HDD 上s.写流将无法跟上,并将开始在内部缓冲区中存储数据.一旦缓冲区达到 highWaterMark(默认为 16KB),写入将开始返回 false,并且流将在内部排队排空.一旦内部缓冲区的长度为 0,就会触发 drain 事件.

Now imagine that the file read is on a SSD and can read at 500MB/s and write is on a HDD that can only write at 150MB/s. The write stream will not be able to keep up, and will start storing data in the internal buffer. Once the buffer has reached the highWaterMark, which is by default 16KB, the writes will start returning false, and the stream will internally queue a drain. Once the internal buffer's length is 0, then the drain event is fired.

排水管的工作原理:

if (state.length === 0 && state.needDrain) {
  state.needDrain = false;
  stream.emit('drain');
}

这些是作为 writeOrBuffer 函数一部分的排放的先决条件:

And these are the prerequisites for a drain which are part of the writeOrBuffer function:

var ret = state.length < state.highWaterMark;
state.needDrain = !ret;

<小时>

要了解如何使用 drain 事件,请参考 Node.js 文档中的示例.


To see how the drain event is used, take the example from the Node.js documentation.

function writeOneMillionTimes(writer, data, encoding, callback) {
  var i = 1000000;
  write();
  function write() {
    var ok = true;
    do {
      i -= 1;
      if (i === 0) {
        // last time!
        writer.write(data, encoding, callback);
      } else {
        // see if we should continue, or wait
        // don't pass the callback, because we're not done yet.
        ok = writer.write(data, encoding);
      }
    } while (i > 0 && ok);
    if (i > 0) {
      // had to stop early!
      // write some more once it drains
      writer.once('drain', write);
    }
  }
}

该函数的目标是向可写流写入 1,000,000 次.发生的情况是变量 ok 设置为 true,并且循环仅在 ok 为 true 时执行.对于每一次循环迭代,ok 的值被设置为 stream.write() 的值,如果 drain 将返回 false必需的.如果 ok 变为 false,则 drain 的事件处理程序会等待,并在发生时恢复写入.

The function's objective is to write 1,000,000 times to a writable stream. What happens is a variable ok is set to true, and a loop only executes when ok is true. For each loop iteration, the value of ok is set to the value of stream.write(), which will return false if a drain is required. If ok becomes false, then the event handler for drain waits, and on fire, resumes the writing.

就您的代码而言,您不需要使用 drain 事件,因为您只在打开流后立即编写一次.由于您尚未向流中写入任何内容,因此内部缓冲区是空的,您必须以块的形式写入至少 16KB 的内容才能触发 drain 事件.drain 事件用于多次写入比可写流的 highWaterMark 设置更多的数据.

Regarding your code specifically, you don't need to use the drain event because you are writing only once right after opening your stream. Since you have not yet written anything to the stream, the internal buffer is empty, and you would have to be writing at least 16KB in chunks in order for the drain event to fire. The drain event is for writing many times with more data than the highWaterMark setting of your writable stream.

这篇关于如何在Node.js中使用stream.Writable的drain事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆