Как дождаться конца потока?

Есть код:

const readStream = fs.createReadStream("file");
const writeStream = fs.createWriteStream("file");

let test;
writeStream.on("finish", () => {
    test = "Yeah".
});

const pipeline = promsify(stream.pipeline);

await pipeline(readStream, writeStream);
console.log(test)
return test

Знаю такие варианты решения:

while(!test) {
  //Ну и  тут мы спим...
}

И такой вариант решения:

    const a = () => return new Promise(rsolve, reject) => {
       writeStream.on("finish", () => {
          test = "Yeah".
          resolve(test);
       }
    });

pipeline(readStream, writeStream);
await a()

Проблемы:

  • Ну про while говорить не приходится...
  • А вот с промисом... Так, как я сейчас написал - работает, но нужно обратить внимание, что перед pipeline отсутствует await. Если его добавить (await pipeline(readStream, writeStream);) - код замирает. Может его и не нужно ставить?

Как решить такое?


Ответы (1 шт):

Автор решения: nörbörnën

Для наглядности располагаю варианты от событийной работы с потоками до последнего stream/promises.

Вариант использующий только события потоков:

const fs = require('fs');
const path = require('path');

const filesrc = path.join(__dirname, './src.txt');
const filedest = path.join(__dirname, `./dest-${Date.now()}.txt`);

(async () => {
  const readStream = fs.createReadStream(filesrc);
  const writeStream = fs.createWriteStream(filedest);

  try {
    await new Promise((resolve, reject) => {
      writeStream.on('finish', resolve);
      writeStream.on('error', reject);
      readStream.on('error', reject);
      readStream.pipe(writeStream);
    });

    console.log('done');
    console.log(await fs.promises.readdir(__dirname));
  } catch (err) {
    console.error(err);
  }
})();

Вариант использующий stream.pipeline:

const fs = require('fs');
const stream = require('stream');
const path = require('path');

const filesrc = path.join(__dirname, './src.txt');
const filedest = path.join(__dirname, `./dest-${Date.now()}.txt`);

(async () => {
  const readStream = fs.createReadStream(filesrc);
  const writeStream = fs.createWriteStream(filedest);

  try {
    await new Promise((resolve, reject) => {
      stream.pipeline(readStream, writeStream,
        (err) => (err ? reject(err) : resolve()));
    });

    console.log('done');
    console.log(await fs.promises.readdir(__dirname));
  } catch (err) {
    console.error(err);
  }
})();

Вариант использующий stream.pipeline и promisify:

const fs = require('fs');
const stream = require('stream');
const path = require('path');
const { promisify } = require('util');

const filesrc = path.join(__dirname, './src.txt');
const filedest = path.join(__dirname, `./dest-${Date.now()}.txt`);

(async () => {
  const readStream = fs.createReadStream(filesrc);
  const writeStream = fs.createWriteStream(filedest);

  try {
    await promisify(stream.pipeline)(readStream, writeStream);

    console.log('done');
    console.log(await fs.promises.readdir(__dirname));
  } catch (err) {
    console.error(err);
  }
})();

Вариант использующий stream/promises:

const fs = require('fs');
const stream = require('stream/promises');
const path = require('path');

const filesrc = path.join(__dirname, './src.txt');
const filedest = path.join(__dirname, `./dest-${Date.now()}.txt`);

(async () => {
  const readStream = fs.createReadStream(filesrc);
  const writeStream = fs.createWriteStream(filedest);

  try {
    await stream.pipeline(readStream, writeStream);

    console.log('done');
    console.log(await fs.promises.readdir(__dirname));
  } catch (err) {
    console.error(err);
  }
})();
→ Ссылка