web-dev-qa-db-ja.com

node.js + expressで「応答終了」イベントをキャプチャするにはどうすればよいですか?

存在する場合は、応答の「終了」イベントでリスナーを設定するエクスプレスミドルウェア関数を記述したいと思います。目的は、エンドハンドラーが送信することを決定したhttp応答コードに基づいてクリーンアップを行うことです。 dbトランザクションの応答コードとロールバック/コミットのログ。つまり、このクリーンアップをエンドコール元に透過的にしたいのです。

私は次のようなことを速達でしたいと思います:

ルートミドルウェア

_function (req, res, next) {
   res.on ('end', function () {
      // log the response code and handle db
      if (res.statusCode < 400) { db.commit() } else { db.rollback() }
   });
   next();
}
_

ルート:

_app.post ("/something", function (req, res) { 
    db.doSomething (function () {
       if (some problem) {
          res.send (500);
       } else {
          res.send (200);
       }
    });
 }
_

これを試してみると、「終了」イベントハンドラーが呼び出されません。 res.on('close')についても同じです。これについては、別の投稿で説明しています。そのようなイベントは発生しますか?

私がこれを行うと考えることができる他の唯一の方法は、カスタムミドルウェアで_res.end_または_res.send_を自分のバージョンでラップすることです。 _res.end_と_res.send_はコールバックを取得しないため、これを理想的にすることはできません。これらをラップし、オリジナルを呼び出して、設定した応答コードに基づいて処理を行うことはできません。電話をかけ直します(電話でかけ直されないため)。

これを行う簡単な方法はありますか?

34
Jake

documentation を読むと、ここに_res.send_の署名があります。

_res.send(body|status[, headers|status[, status]])
_

つまり、res.send( 'some string', 200 );またはres.send( 404 );のように、独自のステータスを設定できます。

このメソッドは、送信応答に使用する方法です。

クライアントに送信されるとアクセスできなくなるため、コールバックはありません。

これはサーバーが最後に行うことです。要求を処理すると、応答を送信します。

ただし、アクセスすることはできますbeforeクライアントに送信します。つまり、次のことができます。

_console.log( res );
res.send( datas );
_

ロールバック/コミットする場合は、応答がなくなったときではなく、データベースのコールバックが呼び出されたときに行います。

2

不思議なことに、応答が閉じたときに応答が「finish」イベントを発行するように見えます: http://sambro.is-super-awesome.com/2011/06/27/listening-for-end- of-response-with-nodeexpress-js /

このブログエントリは少し古いにもかかわらず、このイベントはまだ存在します( lib/http.jsの836行目 )。そのため、ノードもドキュメントもドキュメントに記載されていなくても、すぐに消えることはないと思いますそれ。 2014年の初めまでに lib/_http_outgoing.jsの504行目 に移動し、引き続き機能します。

ちなみに、サーバー応答の「エラー」イベントは、おそらく通常は見たいものではありません。

43
Aveius

@Amatsuyuの応答をさらに進めるために、次のようにします。

res.on('finish', function() {
  // do stuff here
});
30
dmon