drain
事件是指可写流的内部缓冲区已被清空时触发的事件。
仅当内部缓冲区的大小超过其
highWaterMark
属性时,才会发生这种情况。该属性是可写流的内部缓冲区中可以存储的最大数据字节数,直到停止从数据源读取数据为止。
这种情况的原因可能是涉及从一个流中读取数据源的设置比将数据写入另一个资源的速度更快。例如,考虑两个流:
var fs = require('fs');
var read = fs.createReadStream('./read');
var write = fs.createWriteStream('./write');
现在假设文件
read
存储在SSD上,读取速度为500MB/s,而
write
存储在HDD上,只能以
150MB/s
的速度写入。写入流将跟不上,开始将数据存储在内部缓冲区中。一旦缓冲区达到默认值16KB的
highWaterMark
,写入将开始返回
false
,并且流将在内部排队等待。一旦内部缓冲区的长度为0,
drain
事件就会被触发。
这就是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) {
writer.write(data, encoding, callback);
} else {
ok = writer.write(data, encoding);
}
} while (i > 0 && ok);
if (i > 0) {
writer.once('drain', write);
}
}
}
该函数的目标是向可写流写入1,000,000次。当变量
ok
被设置为true时,循环才会执行。在每次循环迭代中,
ok
的值会被设置为
stream.write()
的返回值,如果需要
drain
,则该函数返回false。如果
ok
变成了false,那么等待
drain
的事件处理程序将会暂停,直到触发事件后恢复写入。
就你的代码而言,你不需要使用
drain
事件,因为你只是在打开流之后立即写入一次。由于你还没有向流中写入任何东西,内部缓冲区为空,除非以16KB的大小写入块,否则
drain
事件不会触发。
drain
事件适用于多次写入比你可写流的
highWaterMark
设置更多数据的情况。
drain
事件。 - hexacyanidedrain
的上下文。 - hexacyanidewriter
是任何可写流的实例。可以从它必须具有write
方法和drain
事件来推断。 - hexacyanide