该drain
事件用于可写流的内部缓冲区已被清空。
只有当内部缓冲区的大小超过其highWaterMark
属性时才会发生这种情况,该属性是可写流的内部缓冲区中可以存储的最大数据字节数,直到它停止从数据源读取为止。
出现这种情况的原因可能是由于设置涉及从一个流中读取数据源的速度快于将其写入另一个资源的速度。例如,取两个流:
var fs = require('fs');
var read = fs.createReadStream('./read');
var write = fs.createWriteStream('./write');
现在假设该文件read
位于 SSD 上,可以以 500MB/s 的速度读取,而write
位于只能以150MB/s
. 写入流将无法跟上,并将开始将数据存储在内部缓冲区中。一旦缓冲区达到highWaterMark
默认值 16KB,写入将开始返回false
,并且流将在内部排队排空。一旦内部缓冲区的长度为 0,则drain
触发事件。
这是排水管的工作原理:
if (state.length === 0 && state.needDrain) {
state.needDrain = false;
stream.emit('drain');
}
这些是作为writeOrBuffer
功能一部分的排水的先决条件:
var ret = state.length < state.highWaterMark;
state.needDrain = !ret;
要查看如何使用drain
事件,请以 Node.js 文档中的示例为例。
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()
,如果需要 a 则返回 false drain
。如果ok
变为 false,则drain
等待事件处理程序并在着火时恢复写入。
特别是关于您的代码,您不需要使用该drain
事件,因为您在打开流后只编写一次。由于您尚未向流中写入任何内容,因此内部缓冲区是空的,您必须以块的形式写入至少 16KBdrain
才能触发事件。该drain
事件用于多次写入比highWaterMark
可写流设置更多的数据。