gist

2012年1月9日月曜日

throw e; // process.nextTick error, or 'error' event on first tick

Nodeは、1つのイベントループですべてのイベントに対応します。補足していない例外が1つでも発生した場合、Nodeは処理を停止してしまします。プログラマは例外処理を記述するのが基本かと思いますが、理解不足やプロジェクトの初期段階では補足できない例外も多々あるかと。

例えば、以下のようなコードがあるとします。

uncaught_exceptions.js

var http = require('http');

http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type':'text/plain'});
    res.write('Hello World!');
    res.end();
    res.send();
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

実行して、ブラウザからアクセスしてみます。すると例外が発生しNodeが停止します。

$ node uncaught_exceptions.js 
Server running at http://127.0.0.1:1337/

/Users/inouetomoyuki/Dropbox/Projects/node/uncaught_exceptions/uncaught_exceptions.js:12
    res.send();
        ^
TypeError: Object #<ServerResponse> has no method 'send'
    at Server.<anonymous> (/Users/inouetomoyuki/Dropbox/Projects/node/uncaught_exceptions/uncaught_exceptions.js:12:9)
    at Server.emit (events.js:70:17)
    at HTTPParser.onIncoming (http.js:1479:12)
    at HTTPParser.onHeadersComplete (http.js:102:31)
    at Socket.ondata (http.js:1375:22)
    at TCP.onread (net.js:334:27)

TypeErrorのところに「TypeError: Object #<ServerResponse> has no method 'send'(ServerResponseオブジェクトにsendというメソッドはありません)」とあります。

この例外処理を追記してみます。

var http = require('http');

process.on('uncaughtException', function(err) {
    console.log(err);
});

http.createServer(function(req, res) {
    ...

実行し、再度ブラウザからアクセスしてみます。

$ node uncaught_exceptions.js 
Server running at http://127.0.0.1:1337/
[TypeError: Object #<ServerResponse> has no method 'send']

Nodeは停止せずに補足した例外がコンソールに出力されます。

Nodeでは、補足できなかった例外があると最終的にprosessモジュールからuncaughtExceptionイベントが発生します。このイベント処理を記述することですべての例外を補足でき、Nodeを停止しないようにできます。

繰り返しになりますが、プログラマの責任として、例外処理をきちんと記述しなければなりません。あくまでこの処理は例外を潰しつくした上で、最終的なセーフティネットとして利用するようにしましょう。

参考: [Tech][JS][Node] Node.js のエラーハンドリング

0 件のコメント: