如何在Node.js中使用stream.Writable的drain事件 [英] How to use drain event of stream.Writable in Node.js
问题描述
在 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屋!