このdrainイベントは、書き込み可能なストリームの内部バッファーが空になったときのものです。
これは、内部バッファーのサイズがそのhighWaterMarkプロパティを超えた場合にのみ発生します。これは、データ ソースからの読み取りを停止するまで、書き込み可能なストリームの内部バッファー内に格納できるデータの最大バイト数です。
このような問題の原因は、あるストリームからのデータ ソースの読み取りが、別のリソースへの書き込みよりも高速であることが原因である可能性があります。たとえば、次の 2 つのストリームがあります。
var fs = require('fs');
var read = fs.createReadStream('./read');
var write = fs.createWriteStream('./write');
ここで、ファイルreadが SSD 上にあり、500MB/s で読み取ることwriteができ、HDD 上にあると想像してください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 に設定され、が true の場合にのみループが実行されokます。ループの反復ごとに、 の値が の値にok設定され、stream.write()a が必要な場合は false が返されますdrain。false になるとok、イベント ハンドラーがdrain待機し、発生すると、書き込みを再開します。
特にコードに関してはdrain、ストリームを開いた直後に一度だけ書き込むため、イベントを使用する必要はありません。ストリームにはまだ何も書き込んでいないため、内部バッファーは空であり、drainイベントを発生させるには、少なくとも 16 KB のチャンクを書き込む必要があります。イベントは、書き込み可能なストリームdrainの設定よりも多くのデータを何度も書き込むためのものです。highWaterMark