這篇文章主要介紹“Node端異常捕獲怎么實現”,在日常操作中,相信很多人在Node端異常捕獲怎么實現問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Node端異常捕獲怎么實現”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
try...catch是大家最常用的錯誤處理機制,Javascript語言內置的錯誤處理機制可以在檢測到代碼異常的時候直接進行捕獲并處理。
function test() { try { throw new Error("error"); } catch(e) { console.log(e); } finally { console.log("finally"); } } test()
一般來說,throw 用于拋出異常,但是單純從語言的角度,我們可以拋出任何值,也不一定是異常邏輯,但是為了保證語義清晰,不建議用 throw 表達任何非異常邏輯。try 語句用于捕獲異常,用 throw 拋出的異常,可以在 try 語句的結構中被處理掉:try 部分用于標識捕獲異常的代碼段,catch 部分則用于捕獲異常后做一些處理,而 finally 則是用于執行后做一些必須執行的清理工作。catch 結構會創建一個局部的作用域,并且把一個變量寫入其中,需要注意,在這個作用域,不能再聲明變量 e 了,否則會出錯。在 catch 中重新拋出錯誤的情況非常常見,在設計比較底層的函數時,常常會這樣做,保證拋出的錯誤能被理解。finally 語句一般用于釋放資源,它一定會被執行,我們在前面的課程中已經討論過一些 finally 的特征,即使在 try 中出現了 return,finally 中的語句也一定要被執行。
大多數Node.js核心API都提供的是利用回調函數處理錯誤,之所以采用這種錯誤處理機制,是因為異步方法所產生的方法并不能簡單地通過try...catch機制進行攔截。
const fs = require('fs'); function read() { fs.readFile("/some/file/does-not-exist", (err, data) => { if(err) { throw new Error("file not exist"); } console.log(data); }); } read();
Promise是用于處理異步調用的規范,由于 JavaScript 特殊的 EventLoop 機制,由 Promise 異步產生錯誤是沒有辦法使用 try...catch
的。
Promise提供的錯誤處理機制,是通過catch方法進行捕獲。
try { Promise.reject() } catch(err) { // 這里啥都 catch 不到 console.log(err) }
fs.copy( buildStatic, aresStatic ).then(() => { console.log(`${buildStatic} -> ${aresStatic}`) }).catch(err => { // 這里可以捕獲到報錯 console.log(err) })
async/await語法糖加上try...catch語句進行的。這樣做的好處是異步和同步調用都能夠使用統一的方式進行處理了。
對于異步代碼,建議統一轉換成Promise然后采用async/await + try...catch這種方式進行處理。這樣風格統一,程序的健壯性也大大加強。
async function one() { // a未定義 a.b = 3 } async function test() { try { await one(); } catch(error) { // a is not defined console.log(error); } } test();
實際開發中,總是會有一些 Promise 被遺漏掉catch處理,沒有得到錯誤處理,會導致應用crash。我們可以通過**unhandledrejection
** 事件捕獲未處理的 Promise 錯誤。
實現原理:Node.js 會在每次 Tick 執行完后檢查是否有未捕獲的錯誤 Promise,如果有,則觸發 unhandledRejection
事件。
process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at:', p, 'reason:', reason); });
如果是回調函數中捕獲異常怎么做?用domain去捕獲,domian捕獲會拋出500錯誤,但是domain捕獲有一個問題,會丟失棧信息,無法保證程序健康進行,所以要結束進程,在回調函數中process.exit(1)
,然后用node的server.close方法再去釋放,server.close連接釋放后自動結束進程,所以不用在server.close中去結束進程process.exit(1)
uncaughtExpection捕獲異常的的原理就是:uncaughtExpection事件存在回調函數process.on("uncaughtExpection",callback)
時node不會強制結束進程,這樣可彌補domain丟失stack的問題
所以domian去捕獲絕大部分回調函數中的異常,uncaughtExpection去捕獲丟失stack異常,這樣就完整了
app.use(function(req,res,next){ var reqDomain = domain.create(); reqDomain.on("err",function(){ try { var killTimer = setTimeout(function(){ process.exit(1); },1000) killTimer.unref(); server.close(); res.send(500); } catch(e) { // statements console.log(e.stack); } }) reqDomain.run(next); }); process.on("uncaughtException",function(err){ console.log(err); try{ var killTimer = setTimeout(function(){ process.exit(1) },1000) killTimer.unref(); server.close(); }catch(e){ console.log(e.stack); } });
uncaughtException
也是 NodeJS 進程的一個事件。如果進程里產生了一個異常而沒有被任何Try Catch
捕獲會觸發這個事件。
NodeJS 對于未捕獲異常的默認處理是:
- 觸發 uncaughtException
事件
- 如果 uncaughtException 沒有被監聽
- 打印異常的堆棧信息
- 觸發進程的 exit 事件
所以如果某個報錯沒有被任意try catch捕獲,且沒有定義uncaughtException事件,就會導致程序退出。
process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at: Promise', p, 'reason:', reason) })
Express中,路由或中間件報錯處理可以通過特殊的中間件來完成。
一般中間件的參數為3個:req
,res
, next
。如果你use
一個4個參數的中間件,它將被Express視為錯誤處理中間件。
app.get('/a',function(req,res,next){ res.end('hahah'); next(new Error('錯誤啦')); }); app.use('/a',function(err,req,res,next){ console.log('路由錯誤'+err); }) //all error中間件 app.use(function(err, req, res, next) { console.log("Error happens", err.stack); }); //錯誤傳遞,/a的錯誤處理首先匹配/a那個錯誤中間件,如果不用next就不會傳遞到全局錯誤處理中間件 //如果在/a錯誤處理中間件里調用next(err) 那么全局錯誤中間件也會被執行
到此,關于“Node端異常捕獲怎么實現”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。