web-dev-qa-db-ja.com

Node.jsExpressアプリは起動エラーを処理します

Node.jsとExpressにアプリがあります。テストを書く必要があります。 Expressアプリのエラーの処理に問題があります。私はこれを見つけました EADDRINUSEのようなnode.js/expressサーバーエラーをキャッチするにはどうすればよいですか? 、しかしそれは私にとってはうまくいきません、理由はわかりません。 expressApp.listen()の実行中に発生する可能性のあるエラー(EADDRINUSE、EACCESなど)を処理したいと思います。

express = require('express')
listener = express()

#doesn't work for me
listener.on('uncaughtException', (err) ->
  #do something
)

#doesn't work too
listener.on("error", (err) ->
  #do something
)

#this works, but it caughts all errors in process, I want only in listener
process.on('uncaughtException', (err) ->
  #do something
)

listener.listen(80) #for example 80 to get error

何か案は?

19
Piane_Ramso

まず、expressJSはuncaughtExceptionイベントをスローしませんが、プロセスはスローします。そのため、コードが機能しないのは当然です。

したがって、代わりにprocess.on('uncaughtException',handler)を使用してください。

次に、expressJSは、次のように、この目的のために提供するミドルウェア関数を使用するという、エラー処理の標準的な手段をすでに提供しています。

app.configure(function(){
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

この関数は、オプションのスタックトレースを使用してエラーメッセージをクライアントに返します。これについては、 connectJS errorHandler に記載されています。

(errorHandlerは実際にはconnectJSの一部であり、expressJSによってのみ公開されることに注意してください。)

既存のerrorHandlerが提供する動作がニーズに十分でない場合、そのソースは connectJSのerrorHandlerミドルウェア にあり、ニーズに合わせて簡単に変更できます。

もちろん、この関数を直接変更するのではなく、これを行う「正しい」方法は、次のように、connectJSバージョンを開始点として使用して独自のerrorHandlerを作成することです。

var myErrorHandler = function(err, req, res, next){
    ...
    // note, using the typical middleware pattern, we'd call next() here, but 
    // since this handler is a "provider", i.e. it terminates the request, we 
    // do not.
};

そして、次のようにexpressJSにインストールします。

app.configure(function(){
    app.use(myErrorHandler);
});

ConnectJSのfilterおよびproviderミドルウェアの考え方の説明については、 Just Connect it、Already および Connect/Express用のミドルウェアの書き方 を参照してください。よく書かれたチュートリアルのために。

また、これらが役立つ場合があります。

最後に、expressJSのテストに関する優れた情報源は、 独自のテスト にあります。

22
Rob Raisch

これでうまくいくはずです:

listener.listen(80).on('error', function(err) { });

listener.listen実際には、HTTPサーバーを作成し、そのサーバーでlistenを呼び出します。

app.listen = function(){
  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};
70
Marius Tibeica

言及:Marius Tibeica回答は完全で素晴らしいです、またdavid_pコメントは。 Rob Raischの答えもそうです(探索するのは興味深いです)。 https://stackoverflow.com/a/27040451/7668448
https://stackoverflow.com/a/13326769/7668448

これが便利だと思う人のために、ここではビジーポート処理を実装する関数です(ポートがビジーの場合、ビジーポートがなくなるまで次のポートで試行します)

app.portNumber = 4000;
function listen(port) {
    app.portNumber = port;
    app.listen(port, () => {
        console.log("server is running on port :" + app.portNumber);
    }).on('error', function (err) {
        if(err.errno === 'EADDRINUSE') {
            console.log(`----- Port ${port} is busy, trying with port ${port + 1} -----`);
            listen(port + 1)
        } else {
            console.log(err);
        }
    });
}

listen(app.portNumber);

関数listenは、それ自体を再帰的に呼び出しています。ポートビジーエラーの場合。毎回ポート番号をインクリメントします。

1
Mohamed Allal