前段時間學習《深刻淺出Nodejs》時,在第四章 - 異步編程中做者樸靈曾提到,異步編程的難點之一是異常處理,書中描述"嘗試對異步方法進行try/catch操做只能捕獲當次事件循環內的異常,對call back執行時拋出的異常將無能爲力"。編程
果真,項目測試過程當中,連續兩天遇到了Node.js進程Crash的問題。經過Debug Log,究其緣由,發現正是書中提到的問題。異步
例如, 異步編程
1 //test.js 2 3 var test = undefined; 4 5 try{ 6 var f1 = function(){ 7 console.log(test.toString()); 8 } 9 } 10 catch(e){ 11 console.log('error..'); 12 } 13 14 //assume somewhere f1() will be called as an call back function 15 f1();
這裏模仿f1函數是作爲call back(回調)函數傳遞給其餘函數,在其餘函數執行過程當中執行call back的函數。從代碼表面來看,很容易認爲若是Line 7, 函數
1 console.log(test.toString());
若是這行code發生異常,會天然認爲其會被try catch捕獲到,並不會引發進程的Crash。但其實,運行結果是:學習
運行錯誤,Line 11的錯誤並無打印,說明在程序中錯誤沒有被Try Catch。而Nodejs做爲單進程單線程程序,將會引發進程的Crash!測試
------------------------------------------------------------------------------------------------------------------------spa
所以,在進行異步編程時,我的以爲:線程
要考慮到call back函數可能產生的錯誤,增長類型檢查代碼或在Call back被真正執行的地方增長Try cach等,避免異常未能被捕獲致使進程Crash
code
------------------------------------------------------------------------------------------------------------------------blog
如本例,可修改以下,
1 if(typeof(test) != 'undefined'){ 2 console.log(test.toString()); 3 }
或者
1 console.log(test? test.toString() : '[undefine]');
或者
1 try{ 2 f1(); 3 } 4 catch(e) 5 { 6 console.log('new error..'); 7 }
這樣,再次運行程序,就能夠避免異常,避免進程的Crash。
小結:
在Node.js中,很是多的異步調用API,在執行API,傳入Call back函數時,必定要注意Call back函數裏可能發生的錯誤,若是沒有被正常的Try catch到或者其餘方式避免,就有可能致使進程的Crash。
Best Regards
Kevin Song
2014/6/25