该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可写流设置更多的数据。