ストリーム
stream
データの流れ(stream)を扱うデータ構造
データの塊が非同期的に繰り返し流れてくる
例:巨大なファイルをまとめて読み書きするとパフォーマンス上の問題が出る
jsasync function copyFile(src, dest) {
const data = await fs.readFile(src); // ここでファイル全体をBufferに読み込んでいる
return await fs.writeFile(dest, data); // ここでBufferからファイル全体を書き込んでいる
}
データの内容が全部メモリに載るのでメモリが圧迫される
データの内容がデカすぎてデータ構造に入りきらない
Node.jsの
Bufferには2147483647bytes以上のデータが入らない
ストリームを使い、ファイルを少しずつ読み込んで少しずつ書き込むことで効率を高める
jsasync function copyFileStream(src, dest) {
return new Promise((resolve) =>
fs
.createReadStream(src)
.pipe(fs.createWriteStream(dest))
.on("finish", resolve)
);
}
非同期IOだけでは不十分
fs.createReadStream
でファイルから内容を読みだすReadableStreamを作る
fs.createWriteStream
でファイルに内容を書き込むWritableStreamを作る
on-data.jsstream.on("data", chunk => {
console.log(`data: ${chunk}`);
})
stream.on('error', error => {
console.error(`error: ${error}`)
})
stream.on('end', () => {
console.log(`end.`)
})
現在の ECMAScript では AsyncIterator
が実質的にストリームとして扱える
for-await-of 構文で手続き的に扱える
当たり前だが実行をブロックする
for-await-of.jstry {
for await(const chunk of stream) {
console.log(`data: ${chunk}`);
}
} catch (error) {
console.error(`error: ${error}`);
}
console.log(`end.`)
『Callback to Promise and beyond 』