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

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

问题描述

在Node.js中,我使用 fs.createWriteStream 方法将数据附加到本地文件。在节点文档中,当使用 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);

在上面的代码中,我如何使用排水事件?事件是否在下面正确使用?

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 event用于清空可写流的内部缓冲区。

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,位于硬盘上,只能写入 150MB / 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.

这是排水工作的方式:

This is how a drain works:

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

这些是排水的先决条件,是<$ c的一部分$ c> writeOrBuffer function:

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

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






查看的方法使用了排放事件,从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.

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

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