1. ホーム
  2. javascript

[解決済み] Node.js 複数の(書き込み可能な)ターゲットに同じ読み込み可能なストリームをパイプする

2023-04-30 10:55:45

質問

私は、同じストリームからデータを読み取る必要がある 2 つのコマンドを直列に実行する必要があります。 ストリームを別のストリームにパイプした後、バッファが空になるので、そのストリームからデータを再び読み取ることができないので、これは動作しません。

var spawn = require('child_process').spawn;
var fs = require('fs');
var request = require('request');

var inputStream = request('http://placehold.it/640x360');
var identify = spawn('identify',['-']);

inputStream.pipe(identify.stdin);

var chunks = [];
identify.stdout.on('data',function(chunk) {
  chunks.push(chunk);
});

identify.stdout.on('end',function() {
  var size = getSize(Buffer.concat(chunks)); //width
  var convert = spawn('convert',['-','-scale',size * 0.5,'png:-']);
  inputStream.pipe(convert.stdin);
  convert.stdout.pipe(fs.createWriteStream('half.png'));
});

function getSize(buffer){
  return parseInt(buffer.toString().split(' ')[2].split('x')[0]);
}

リクエスト はこれについて文句を言う

Error: You cannot pipe after data has been emitted from the response.

を変更し inputStream fs.createWriteStream は、もちろん同じ問題をもたらします。 ファイルに書き込みたくないけど 再利用 というストリームを何らかの方法で再利用したいのです。 を要求する が生成するストリーム(あるいはそれ以外のもの)に何らかの形で影響を与えます。

一度パイプ処理を終了した読み込み可能なストリームを再利用する方法はありますか? 上記の例のようなことを達成するための最良の方法は何でしょうか?

どのように解決するのですか?

2つのストリームにパイプで接続し、ストリームの複製を作成する必要があります。PassThroughストリームを使えば、単純に入力を出力に渡すだけのストリームを作成することができます。

const spawn = require('child_process').spawn;
const PassThrough = require('stream').PassThrough;

const a = spawn('echo', ['hi user']);
const b = new PassThrough();
const c = new PassThrough();

a.stdout.pipe(b);
a.stdout.pipe(c);

let count = 0;
b.on('data', function (chunk) {
  count += chunk.length;
});
b.on('end', function () {
  console.log(count);
  c.pipe(process.stdout);
});

出力します。

8
hi user