<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                &emsp;&emsp;在 Node.js 中,提供了[error](https://nodejs.org/dist/latest-v18.x/docs/api/errors.html)模塊,并且內置了標準的 JavaScript 錯誤,常見的有: * EvalError:在調用 eval() 函數時出現問題時拋出該錯誤。 * SyntaxError:調用不符合 JavaScript 的語法時拋出該錯誤。 * RangeError:超出可接受值的集合或范圍,例如數組越界。 * ReferenceError:訪問未定義的變量時拋出該錯誤。 * TypeError:參數或變量的類型有問題時拋出該錯誤。 * URIError:使用全局的 URI 處理函數發生問題時拋出該錯誤。 &emsp;&emsp;本系列所有的示例源碼都已上傳至Github,[點擊此處](https://github.com/pwstrick/node)獲取。? ## 一、Error 類 &emsp;&emsp;Node.js 生成的上述錯誤,都是 Error 類的實例或繼承自 Error 類。注意,運行時拋出的所有異常都將是 Error 的實例。 &emsp;&emsp;Error 實例能捕獲堆棧跟蹤,并提供錯誤的文本描述。 &emsp;&emsp;下面是一個簡單的示例,其中 message 屬性提供了錯誤的字符串描述,toString() 會生成文本消息。 &emsp;&emsp;stack 屬性提供了完整的錯誤信息,包括錯誤描述和一系列堆棧幀(每行以 "at " 開頭),每一幀都描述了代碼中生成錯誤的調用點。 ~~~ const e = new Error('test error'); // test error console.log(e.message); // Error: test error console.log(e.toString()); // Error: test error // at Object.<anonymous> (/Users/code/web/node/08/error.js:1:11) // at Module._compile (node:internal/modules/cjs/loader:1108:14) // at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10) // at Module.load (node:internal/modules/cjs/loader:988:32) // at Function.Module._load (node:internal/modules/cjs/loader:828:14) // at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12) // at node:internal/main/run_main_module:17:47 console.log(e.stack); ~~~ ## 二、捕獲錯誤 &emsp;&emsp;一些異常在 JavaScript 層是不可恢復的,會導致 Node.js 進程崩潰。 &emsp;&emsp;所以有些異常需要被捕獲,在 Node.js 中有 3 種常用的捕獲方法: * 錯誤優先的回調。 * throw 語句或 try-catch 語句。 * error 事件機制。 **1)錯誤優先的回調** &emsp;&emsp;Node.js 核心模塊暴露的大多數異步方法都遵循錯誤優先回調的慣用模式。 &emsp;&emsp;使用這種模式,回調函數作為參數傳給方法,當操作完成或出現錯誤時,回調函數將使用 Error 實例作為第一個參數傳入。 &emsp;&emsp;如果沒有出現錯誤,則第一個參數將作為 null 傳入。在下面的示例中,當讀取一個不存在的文件時,將拋出錯誤。 ~~~ const fs = require('fs'); function errorCallback(err, data) { // [Error: ENOENT: no such file or directory, open './data.txt'] { // errno: -2, // code: 'ENOENT', // syscall: 'open', // path: './data.txt' // } console.log(err); } fs.readFile('./data.txt', errorCallback); ~~~ **2)throw** &emsp;&emsp;throw 關鍵字后面可以跟任何類型的 JavaScript 值(字符串、數字或對象等)。 &emsp;&emsp;不過在 Node.js 中,throw 不會拋出字符串,而僅拋出 Error 實例。 &emsp;&emsp;直接拋出 Error 實例,和拋出其他類型的值,前者會顯示堆棧幀,而后者不會,如下所示。 ~~~ // /Users/code/web/node/08/throw.js:2 // throw new Error('test error'); // ^ // Error: test error // at test (/Users/code/web/node/08/throw.js:2:9) // at Object.<anonymous> (/Users/code/web/node/08/throw.js:7:1) // at Module._compile (node:internal/modules/cjs/loader:1108:14) // at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10) // at Module.load (node:internal/modules/cjs/loader:988:32) // at Function.Module._load (node:internal/modules/cjs/loader:828:14) // at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12) // at node:internal/main/run_main_module:17:47 throw new Error('test error'); // /Users/code/web/node/08/throw.js:2 // throw 'test error'; // ^ // test error // (Use `node --trace-uncaught ...` to show where the exception was thrown) throw 'test error'; ~~~ **3)try-catch** &emsp;&emsp;try-catch 語句不僅能捕獲同步代碼,還能捕獲異步的 async/await 發生的錯誤,如下所示,調用一個不存在的 func() 函數。 ~~~ // 同步代碼 function try1() { try{ func(); }catch(e) { console.log(e); console.log('try-catch end'); } } // async/await async function test() { func(); } async function try2() { try{ await test(); }catch(e) { console.log(e); console.log('async try-catch end'); } } ~~~ &emsp;&emsp;有一點需要注意,try-catch 無法捕獲異步的回調函數,例如定時器、process.nextTick() 中的回調。 ~~~ try { process.nextTick(function () { func(); }); } catch (e) { console.log('nextTick end'); } ~~~ &emsp;&emsp;catch 分支中的打印并不會執行,因為當回調被調用時,周圍的代碼(包括 try-catch)都已經運行好退出了。 **4)error 事件機制** &emsp;&emsp;如果在程序執行過程中出現了未捕獲的異常,那么程序就會崩潰,Node.js 提供了幾個事件來兜底這類未捕獲的異常。 &emsp;&emsp;首先是 process 上的[uncaughtException](https://nodejs.org/dist/latest-v18.x/docs/api/process.html#event-uncaughtexception)事件,當未捕獲的 JavaScript 異常冒泡到事件循環時,就會自動觸發該事件。 &emsp;&emsp;就比如上面那個無法捕獲的 try-catch 問題,注冊了 uncaughtException 事件就能成功捕獲,如下所示。 ~~~ // ReferenceError: func is not defined // at /Users/code/web/node/08/uncaughtException.js:7:5 // at processTicksAndRejections (node:internal/process/task_queues:78:11) process.on('uncaughtException', (err) => { console.log(err); }); ~~~ &emsp;&emsp;在捕獲后,就不會讓程序奔潰,后續代碼也能被順利運行。 &emsp;&emsp;注意,uncaughtException 事件是用于異常處理的粗略機制,僅用作最后的兜底手段,歸根結底,那些異常不能無視還是需要修復的。 &emsp;&emsp;使用 Promise 進行編程時,異常被封裝為“被拒絕的 promise”,有兩種捕獲方式。第一種是使用 promise.catch() 捕獲和處理,并通過 Promise 鏈傳播。 &emsp;&emsp;第二種是注冊 process 的[unhandledRejection](https://nodejs.org/dist/latest-v18.x/docs/api/process.html#event-unhandledrejection)事件,當 Promise 被拒絕并且在事件循環的一個輪詢內沒有錯誤捕獲時,就會觸發此事件。 &emsp;&emsp;unhandledRejection 事件回調程序包含兩個參數,第一個是任意類型的 Promise 被拒絕的理由,第二個是被拒絕的 Promise 對象。 ~~~ process.on('unhandledRejection', (reason, promise) => { console.log(reason); console.log(promise); }); ~~~ &emsp;&emsp;下面是兩種觸發方式,第一種是在 then() 回調中書寫錯誤代碼,第二種是綁定 reject() 方法。 ~~~ // 第一種觸發方式 Promise.resolve().then((res) => { return JSON.pasre(res); // 注意錯別字 pasre }); // 第二種觸發方式 Promise.reject(new Error('資源尚未加載')); ~~~ &emsp;&emsp;unhandledRejection 事件對于檢測和跟蹤尚未處理的被拒絕的 Promise 很有用。 **5)verror** &emsp;&emsp;在下面的示例中,會在異步回調中通過 throw 拋出一個錯誤。 ~~~ function test() { throw new Error('test error'); } function main() { setImmediate(() => test()); } main(); ~~~ &emsp;&emsp;注意觀察下面的堆棧信息,僅僅標注了 test() 函數中出錯的那條語句的位置,但是再往上的 main() 并沒有被標注。 ~~~ /Users/code/web/node/08/verror.js:2 throw new Error('test error'); ^ Error: test error at test (/Users/code/web/node/08/verror.js:2:9) at Immediate.<anonymous> (/Users/code/web/node/08/verror.js:5:22) at processImmediate (node:internal/timers:464:21) ~~~ &emsp;&emsp;當函數的調用深度比較深時,一旦出錯,那么追溯程序完整的執行過程就比較困難。 &emsp;&emsp;目前市面上有一款[verror](https://github.com/TritonDataCenter/node-verror)庫,可以將 Error 實例層層封裝,在每一層附加錯誤信息,最后通過 VError 實例就能獲取調試所需的信息,便于問題的定位。 ~~~ const VError = require('verror'); function test(err) { const err3 = new VError(err, 'test()'); console.log(err3.message); // test(): main(): test error console.log(err3); } function main() { setImmediate(() => { const err1 = new Error('test error'); const err2 = new VError(err1, 'main()'); test(err2); }); } main(); ~~~ &emsp;&emsp;在上面的示例中,先實例化一個 Error 類,然后實例化一個 VError 類,構造函數的第二個參數就是提供給調試用的關鍵信息。 &emsp;&emsp;將 VError 實例作為參數傳遞給 test() 函數,再實例化一個 VError 類,這其實就是層層包裝的過程。 &emsp;&emsp;最后讀取 message 屬性,得到的值是 test(): main(): test error,這些就是附加的數據,以及錯誤描述。 &emsp;&emsp;如果直接打印 VError 實例,那么能得到更多關鍵信息,包括行數,文件路徑等。 ~~~ VError: test(): main(): test error at test (/Users/code/web/node/08/verror.js:3:16) at Immediate._onImmediate (/Users/code/web/node/08/verror.js:11:5) at processImmediate (node:internal/timers:464:21) { jse_shortmsg: 'test()', jse_cause: VError: main(): test error at Immediate._onImmediate (/Users/code/web/node/08/verror.js:10:18) at processImmediate (node:internal/timers:464:21) { jse_shortmsg: 'main()', jse_cause: Error: test error at Immediate._onImmediate (/Users/code/web/node/08/verror.js:9:18) at processImmediate (node:internal/timers:464:21), jse_info: {} }, jse_info: {} } ~~~ 參考資料: [捕獲異常](https://www.nodejs.red/#/nodejs/advanced/uncaugh-exception)?[診斷報告](https://www.nodejs.red/#/nodejs/modules/report)? [餓了么調試面試題](https://github.com/ElemeFE/node-interview/tree/master/sections/zh-cn#%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86%E8%B0%83%E8%AF%95) [\[譯\] NodeJS 錯誤處理最佳實踐](https://cnodejs.org/topic/55714dfac4e7fbea6e9a2e5d) [異常處理與domain](https://yjhjstz.gitbooks.io/deep-into-node/content/chapter13/chapter13-2.html) ***** > 原文出處: [博客園-Node.js精進](https://www.cnblogs.com/strick/category/2154090.html) [知乎專欄-前端性能精進](https://www.zhihu.com/column/c_1611672656142725120) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看