node.js ストリームでのエラー処理 質問する

node.js ストリームでのエラー処理 質問する

ストリームでエラーを処理する正しい方法は何ですか? リッスンできる「エラー」イベントがあることはすでに知っていますが、任意の複雑な状況についてさらに詳しく知りたいです。

まず、単純なパイプ チェーンを実行したい場合はどうすればよいでしょうか。

input.pipe(transformA).pipe(transformB).pipe(transformC)...

そして、エラーが正しく処理されるように、これらの変換を適切に作成するにはどうすればよいでしょうか?

関連するその他の質問:

  • エラーが発生すると、「end」イベントはどうなりますか? 決して発生しないのですか? 時々発生するのですか? 変換/ストリームに依存しますか? ここでの標準は何ですか?
  • パイプを通じてエラーを伝播させるメカニズムはありますか?
  • ドメインはこの問題を効果的に解決しますか? 例があると助かります。
  • 「エラー」イベントから発生するエラーにはスタック トレースがありますか? 時々ありますか? まったくありませんか? そこからスタック トレースを取得する方法はありますか?

ベストアンサー1

変身

変換ストリームは読み取りと書き込みの両方が可能で、非常に優れた「中間」ストリームです。このため、throughストリームと呼ばれることもあります。この点ではデュプレックス ストリームに似ていますが、データを単に送信するのではなく、データを操作するための優れたインターフェイスを提供します。変換ストリームの目的は、ストリームを介してパイプされるデータを操作することです。たとえば、非同期呼び出しを実行したり、いくつかのフィールドを派生させたり、いくつかのものを再マップしたりする必要がある場合があります。


変換ストリームを配置する場所


変換ストリームの作成方法については、ここそしてここあなたがしなければならないことは、次のとおりです。

  1. ストリームモジュールを含める
  2. Transformクラスをインスタンス化(または継承)する
  3. _transformを受け取るメソッドを実装します(chunk, encoding, callback)

チャンクはデータです。 で作業している場合、ほとんどの場合、エンコードについて心配する必要はありませんobjectMode = true。チャンクの処理が完了すると、コールバックが呼び出されます。その後、このチャンクは次のストリームにプッシュされます。

ストリームを非常に簡単に実行できる便利なヘルパーモジュールが必要な場合は、2 を通して

エラー処理については、読み続けてください。

パイプ

パイプチェーンでは、エラーの処理は確かに簡単ではありません。このスレッド.pipe() はエラーを転送するようには構築されていません。つまり、次のようなものになります...

var a = createStream();
a.pipe(b).pipe(c).on('error', function(e){handleError(e)});

... は、ストリーム 上のエラーのみをリッスンしますc。 でエラー イベントが発行された場合a、それは渡されず、実際にはスローされます。これを正しく行うには、次の操作を行います。

var a = createStream();
a.on('error', function(e){handleError(e)})
.pipe(b)
.on('error', function(e){handleError(e)})
.pipe(c)
.on('error', function(e){handleError(e)});

さて、2 番目の方法はより冗長ではありますが、少なくともエラーが発生した場所のコンテキストを保持できます。これは通常、良いことです。

しかし、宛先でのエラーのみをキャプチャしたい場合や、どこで発生したかはあまり気にしない場合に役立つライブラリが1つあります。イベントストリーム

終わり

エラー イベントが発生すると、終了イベントは (明示的に) 発生しません。エラー イベントが発生すると、ストリームが終了します。

ドメイン

私の経験では、ドメインはほとんどの場合、非常にうまく機能します。処理されないエラー イベント (つまり、リスナーのないストリームでエラーが発生する) がある場合、サーバーがクラッシュする可能性があります。上記の記事で指摘されているように、ストリームをドメインでラップすると、すべてのエラーを適切にキャッチできます。

var d = domain.create();
 d.on('error', handleAllErrors);
 d.run(function() {
     fs.createReadStream(tarball)
       .pipe(gzip.Gunzip())
       .pipe(tar.Extract({ path: targetPath }))
       .on('close', cb);
 });

ドメインの優れた点は、スタック トレースが保持されることです。ただし、event-stream もこの点については優れています。

さらに詳しくは、ストリームハンドブック1 . かなり詳細ですが、非常に役立ち、多くの役立つモジュールへの素晴らしいリンクが提供されています。

1:注: 元の GitHub リポジトリは 2022 年 8 月頃に削除されたため、このリンクは archive.org を指しています。

おすすめ記事