Node.js
例外処理
サーチ…
Node.Jsで例外を処理する
Node.jsには、例外/エラーを処理する3つの基本的な方法があります。
- try - catchブロック
-
callback
への最初の引数としてのエラー -
emit
持つEventEmitterを使用してエラーイベントを
try-catchは、同期コードの実行からスローされた例外を捕捉するために使用されます。呼び出し元(または呼び出し元の呼び出し元など)がtry / catchを使用した場合、エラーをキャッチできます。呼び出し元のどれもtry-catchを持っていない場合、プログラムがクラッシュします。
非同期操作でtry-catchを使用していて、asyncメソッドのコールバックからtry-catchで捕捉されない例外がスローされた場合。非同期操作コールバックから例外をキャッチするには、 約束を使用することをお勧めします。
それをよりよく理解する例
// ** Example - 1 **
function doSomeSynchronousOperation(req, res) {
if(req.body.username === ''){
throw new Error('User Name cannot be empty');
}
return true;
}
// calling the method above
try {
// synchronous code
doSomeSynchronousOperation(req, res)
catch(e) {
//exception handled here
console.log(e.message);
}
// ** Example - 2 **
function doSomeAsynchronousOperation(req, res, cb) {
// imitating async operation
return setTimeout(function(){
cb(null, []);
},1000);
}
try {
// asynchronous code
doSomeAsynchronousOperation(req, res, function(err, rs){
throw new Error("async operation exception");
})
} catch(e) {
// Exception will not get handled here
console.log(e.message);
}
// The exception is unhandled and hence will cause application to break
コールバックは、イベントを非同期に配信するため、Node.jsで主に使用されます。ユーザーは関数(コールバック)を渡し、非同期操作が完了したときにいつか呼び出すことができます。
通常のパターンは、コールバックがコールバック(err、result)として呼び出され、操作が成功したか失敗したかに応じて、errおよびresultのいずれか一方のみがnullでないことです。
function doSomeAsynchronousOperation(req, res, callback) {
setTimeout(function(){
return callback(new Error('User Name cannot be empty'));
}, 1000);
return true;
}
doSomeAsynchronousOperation(req, res, function(err, result) {
if (err) {
//exception handled here
console.log(err.message);
}
//do some stuff with valid data
});
emitより複雑なケースでは、コールバックを使用する代わりに、関数自身がEventEmitterオブジェクトを返すことができ、呼び出し元はエミッタのエラーイベントをリスンすることが予想されます。
const EventEmitter = require('events');
function doSomeAsynchronousOperation(req, res) {
let myEvent = new EventEmitter();
// runs asynchronously
setTimeout(function(){
myEvent.emit('error', new Error('User Name cannot be empty'));
}, 1000);
return myEvent;
}
// Invoke the function
let event = doSomeAsynchronousOperation(req, res);
event.on('error', function(err) {
console.log(err);
});
event.on('done', function(result) {
console.log(result); // true
});
未手当ての例外管理
Node.jsは単一のプロセスで実行されるため、キャッチされない例外はアプリケーションの開発時に注意する必要があります。
静かに例外を処理する
大部分の人々は、node.jsサーバーがエラーを静かに飲み込ませるようにしています。
- 例外を静かに処理する
process.on('uncaughtException', function (err) {
console.log(err);
});
これは悪いですが 、それは動作しますが、
根本的な原因は未知のままであるため、例外(エラー)を引き起こした原因の解決には役立ちません。
何らかの理由でデータベース接続(プール)がクローズした場合、エラーが継続的に伝播します。つまり、サーバーは実行中ですが、dbに再接続しません。
初期状態に戻る
"uncaughtException"の場合は、サーバを再起動して初期状態に戻すと良いでしょう。そこでは動作することがわかっています。例外はログに記録され、アプリケーションは終了しますが、サーバーが稼働していることを確認するコンテナーで実行されるため、サーバーの再始動(最初の稼動状態への復帰)が行われます。
- 永遠(または他のCLIツールをインストールして、ノードサーバーが継続的に稼働していることを確認する)
npm install forever -g
- 永遠にサーバーを起動する
forever start app.js
理由はなぜそれが始まり、私たちが永遠に使用する理由は、サーバーが永遠に終了した後にプロセスがサーバーを再び開始するということです。
- サーバーの再起動
process.on('uncaughtException', function (err) {
console.log(err);
// some logging mechanisam
// ....
process.exit(1); // terminates process
});
また、 クラスタとドメインで例外を処理する方法もありました。
エラーと約束
プロミスは、同期またはコールバック駆動のコードとは異なる方法でエラーを処理します。
const p = new Promise(function (resolve, reject) {
reject(new Error('Oops'));
});
// anything that is `reject`ed inside a promise will be available through catch
// while a promise is rejected, `.then` will not be called
p
.then(() => {
console.log("won't be called");
})
.catch(e => {
console.log(e.message); // output: Oops
})
// once the error is caught, execution flow resumes
.then(() => {
console.log('hello!'); // output: hello!
});
現時点では、約束の中に投げ込まれたエラーが捕捉されず、エラーが飲み込まれ、エラーを追跡することが困難になる可能性があります。これは、 eslintのようなlintingツールを使うか、常にcatch
節を持つようにすることで解決できます。
この動作は、ノードプロセスを終了するために、ノード8で推奨されなくなりました 。