Как читать из одного потока и писать сразу в несколько?
Предположим, у меня есть 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);
Обратите внимание, что вы все равно должны обрабатывать ошибки для каждого потока, поскольку они не распространяются, а места назначения не закрываются, если читаются ошибки.