1. ホーム
  2. node.js

[解決済み] node.jsのストリームによるエラー処理

2022-04-15 19:56:32

質問

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

手始めに、単純なパイプチェーンをしたいときはどうするんだ。

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

また、エラーが正しく処理されるように、これらのトランスフォームを適切に作成するにはどうすればよいのでしょうか?

さらに関連する質問

  • エラーが発生した場合、'end' イベントはどうなるのでしょうか?それは決して発生しないのでしょうか?時々発生するのか?それはトランスフォームやストリームに依存するのでしょうか?ここでの標準は何ですか?
  • パイプを通してエラーを伝播させる仕組みはありますか?
  • ドメインはこの問題を効果的に解決するか?例があるといいですね。
  • error' イベントで出たエラーはスタックトレースされるのか?時々?スタックトレースを取得する方法はあるのでしょうか?

解決方法は?

トランスフォーム

トランスフォームストリームは、読み取りと書き込みの両方が可能なため、実に優れた「中間」ストリームと言えます。このような理由から、トランスフォームストリームは through ストリームです。この点では二重ストリームと似ていますが、単にデータを送るだけでなく、データを操作するための優れたインターフェイスを提供する点が異なります。変換ストリームの目的は、ストリームを通過するデータを操作することです。たとえば、非同期呼び出しや、いくつかのフィールドの導出、リマップなどを行いたい場合があります。



トランスフォームストリームを作成する方法については こちら こちら . あなたがしなければならないことは、:

  1. stream モジュールをインクルードします。
  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番目の方法はより冗長ですが、少なくともエラーが発生する場所のコンテキストを保持することができます。これは通常、良いことです。

しかし、目的地でのエラーだけを捕らえ、どこで発生したかはあまり気にしないという場合に役立つライブラリのひとつが、以下のものだ。 イベントストリーム .

終了

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

ドメイン

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

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);
 });

ドメインの良さは、スタックトレースを保存してくれることです。イベントストリームも同様に良い仕事をしてくれますが。

さらに詳しい情報は ストリームハンドブック . かなり深い内容ですが、非常に便利で、多くの有用なモジュールへの素晴らしいリンクがあります。