先看一個和異步無關(guān)的錯誤處理
var test = undefined;
try{
var f1 = function(){
console.log(test.toString());
}
}
catch(e){
console.log('error..');
}
//TypeError: Cannot read property 'toString' of undefined
//assume somewhere f1() will be called as an call back function
f1();
try catch
中的代碼僅僅是聲明一個變量并且賦值矿咕,除非沒有足夠的內(nèi)存惩歉,否則基本上不會拋出異常似袁,不管f1中的函數(shù)有沒有錯誤狂巢。f1
函數(shù)的調(diào)用根本就沒有包含在try catch
中躏仇,所以拋棄出未捕獲的異常那是100%的事情(至于賦給它的值所指向的函數(shù)有沒有錯誤顯然不在它的職責(zé)范圍之內(nèi),畢竟函數(shù)在這里沒有執(zhí)行恋腕。)抹锄,這個和異步毫無關(guān)系。
在看看跟異步相關(guān)的
node.js是異步IO執(zhí)行,所以我們將try/catch
放置異步回調(diào)函數(shù)中,當(dāng)出現(xiàn)一個異常時,try/catch
操作只能捕獲當(dāng)次事件循環(huán)內(nèi)的異常荠藤,我們通過try
拿到這個錯誤時錯過了當(dāng)前程序運行堆棧伙单。(或者理解成,異步錯誤發(fā)生時在try catch
塊結(jié)束時候哈肖,所以當(dāng)然不會被catch)
之后 Node 會觸發(fā) uncaughtException
事件,而在node.js原生的uncaughtException
處理事件是掛在 process
對象上,所以吻育,如果一個異常出現(xiàn)時,當(dāng)前運行的 process
會直接掛掉,導(dǎo)致錯誤永遠(yuǎn)不會走到 catch
語句.
var test = undefined;
try{
setTimeout(function(){
//TypeError: Cannot read property 'toString' of undefined
console.log(test.toString());
}, 3000)
}
catch(e){
console.log('error..');
}
比如,在實際項目中牡彻,
var deserialize = require('deserialize');
// 假設(shè) deserialize 是一個帶有 bug 的第三方模塊
// app 是一個 express 服務(wù)對象
app.get('/users', function (req, res) {
mysql.query('SELECT * FROM user WHERE id=1', function (err, user) {
var config = deserialize(user.config);
// 假如這里觸發(fā)了 deserialize 的 bug
res.send(config);
});
});
如果不幸觸發(fā)了 deserialize
模塊的 bug
扫沼,這里就會拋出一個異常,最終結(jié)果是整個服務(wù) crash庄吼。
當(dāng)這種情況發(fā)生在 Web 服務(wù)上時結(jié)果是災(zāi)難性的缎除。uncaughtException
錯誤會導(dǎo)致當(dāng)前的所有的用戶連接都被中斷,甚至不能返回一個正常的 HTTP 錯誤碼总寻,用戶只能等到瀏覽器超時才能看到一個no data received
錯誤器罐。
這是一種非常野蠻粗暴的異常處理機制,一個友好的錯誤處理機制應(yīng)該滿足三個條件:
- 對于引發(fā)異常的用戶渐行,返回 500 頁面
- 其他用戶不受影響轰坊,可以正常訪問
- 不影響整個進(jìn)程的正常運行