Как читать из одного потока и писать сразу в несколько?

Предположим, у меня есть readable поток, например request(URL), И я хочу написать свой ответ на диске через fs.createWriteStream() и обвязка с просьбой. Но в то же время я хочу вычислить контрольную сумму загружаемых данных через crypto.createHash() поток.

readable -+-> calc checksum
          |
          +-> write to disk

И я хочу сделать это на лету, без буферизации всего отклика в памяти.

Кажется, что я могу реализовать это с помощью oldschool on('data') крюк. Псевдокод ниже:

const hashStream = crypto.createHash('sha256');
hashStream.on('error', cleanup);

const dst = fs.createWriteStream('...');
dst.on('error', cleanup);

request(...).on('data', (chunk) => {
    hashStream.write(chunk);
    dst.write(chunk);
}).on('end', () => {
    hashStream.end();
    const checksum = hashStream.read();
    if (checksum != '...') {
        cleanup();
    } else {
        dst.end();
    }
}).on('error', cleanup);

function cleanup() { /* cancel streams, erase file */ };

Но такой подход выглядит довольно неловко. Я пытался использовать stream.Transform или же stream.Writable реализовать что-то вроде read | calc + echo | write но я застрял с реализацией.

1 ответ

Решение

Читаемые потоки Node.js имеют .pipe метод, который работает почти так же, как конвейерный оператор unix, за исключением того, что вы можете передавать потоковые объекты js, а также просто строки некоторого типа.

Вот ссылка на документ по трубе

Примером использования в вашем случае может быть что-то вроде:

const req = request(...);
req.pipe(dst);
req.pipe(hash);

Обратите внимание, что вы все равно должны обрабатывать ошибки для каждого потока, поскольку они не распространяются, а места назначения не закрываются, если читаются ошибки.

Другие вопросы по тегам