web-dev-qa-db-ja.com

ノードのパイプメソッドでfs.createWriteStreamを待つ必要がありますか?

パイプの完了を処理するためのコールバック についての質問を見つけたので、書き込みストリームを処理するためにパイプを使用することが同期しているかどうかは非常に混乱しています

fs.renameのような他の人が行う前に、書き込みストリームが確実に行われるようにしたいので、次のようなコードを約束します。

(async function () {
  await promiseTempStream({oldPath, makeRegex, replaceFn, replaceObj, tempPath})
  await rename(tempPath, oldPath)
  function promiseTempStream({oldPath, makeRegex, replaceFn, replaceObj, tempPath}) {
  return new Promise((res, rej) => {
    const writable = fs.createWriteStream(tempPath)
    fs.createReadStream(oldPath, 'utf8')       
      .pipe(replaceStream(makeRegex ,replaceFn.bind(this, replaceObj), {maxMatchLen: 5000}))
    .pipe(writable)
    writable
      .on('error', (err) => {rej(err)})
      .on('finish', res)
    })
}
}())

動作しますが、読んだ後は混乱します pipe doc

デフォルトでは、stream.end()は、ソースの読み取り可能ストリームが「end」を発行したときに宛先の書き込み可能ストリームで呼び出されるため、宛先は書き込み可能ではなくなります。

だから私は必要なだけです

await fs.createReadStream(oldPath, 'utf8')
.pipe(replaceStream(makeRegex ,replaceFn.bind(this, replaceObj), {maxMatchLen: 5000}))
.pipe(fs.createWriteStream(tempPath))
await rename(tempPath, oldPath)

あるいは単に

fs.createReadStream(oldPath, 'utf8')
.pipe(replaceStream(makeRegex ,replaceFn.bind(this, replaceObj), {maxMatchLen: 5000}))
.pipe(fs.createWriteStream(tempPath))
await rename(tempPath, oldPath)

それを行う正しい方法はどれですか?どうもありがとうございました

6
Roy

TempPathストリームでfinishイベントを待つ必要があります。だからあなたは次のようなことをすることができます

async function createTheFile() {
return new Promise<void>(resolve => {
    let a = replaceStream(makeRegex, replaceFn.bind(this, replaceObj), { maxMatchLen: 5000 });
    let b = fs.createWriteStream(tempPath);
    fs.createReadStream(oldPath, 'utf8').pipe(a).pipe(b);
    b.on('finish', resolve);
}
}

await createTheFile();
rename(tempPath, oldPath);

基本的にここでは、tempFileへの書き込みが完了すると解決するpromiseを作成しました。そして、先に進む前に、その約束を待つ必要があります。

ただし、 node.jsストリームでのエラー処理 で説明されているように、ストリームでエラー処理コードも追加すると便利です。

6
akshita007