1. 為什么要處理異常?
如果我們不處理異常的話,直接會導致程序奔潰,用戶體驗比較差,因此我們要對異常進行處理,當出現異常的情況下,我們要給用戶一個友好的提示,並且記錄該異常,方便我們排查。
2. 在Node.js中常用的異常處理方式有哪些?
2.1 使用try catch方式來處理異常,如下代碼:
try { throw new Error('error'); } catch(e) { console.log('異常被捕獲了,我現在還可以繼續執行了'); console.log(e); }
然后執行命令行時候,可以看到如下,也會打印后面的 console.log的信息了;如下所示:
但是使用 try catch 無法處理異步代碼塊內出現的異常,比如如下代碼:
try { setTimeout(() => { throw new Error('error'); }) } catch(e) { console.log('異常被捕獲了,我現在還可以繼續執行了'); console.log(e); }
在命令行中打印信息如下:
可以看到,catch里面的console.log(''); 代碼並沒有被執行。說明catch里面的代碼異常並沒有被捕獲到。
2.2 使用event方式來處理異常
const events = require('events'); // 創建一個事件監聽對象 const emitter = new events.EventEmitter(); // 監聽error事件 emitter.addListener('error', (e) => { // 處理異常信息 console.log(11122222); // 能打印 1112222 說明異常捕獲到了 console.log(e); }); // 觸發 error事件 emitter.emit('error', new Error('你代碼出錯了'));
執行效果如下圖所示:
2.3 callback的方式
比如讀取一個文件,或者創建一個目錄,測試代碼如下:
const fs = require('fs'); fs.mkdir('/dir', (e) => { if (e) { console.log('異常信息處理'); console.log(e); } else { console.log('創建目錄成功'); } });
然后執行結果如下圖所示:
2.4 Promise方式
new Promise((resolve, reject) => { throw new Error('error'); }).then(() => { // 。。。。 }).catch((e) => { console.log('能進來說明可以處理異常信息了'); console.log(e); });
執行結果如下圖所示:
如上是處理同步代碼,但是如果是異步代碼呢?繼續如下代碼測試:
new Promise((resolve, reject) => { setTimeout(() => { throw new Error('error'); }, 100); }).then(() => { // 。。。。 }).catch((e) => { console.log('能進來說明可以處理異常信息了'); console.log(e); });
然后執行結果如下所示:
可以看到,Promise也是一樣無法捕獲異步代碼中的異常信息了。
2.5 Async/Await 方式
Async/Await 也是基於Promise的,Promise是無法捕獲異步異常,因此Async/Await 也是沒有辦法捕獲的。如下測試代碼:
先看同步代碼可以捕獲到的,代碼如下:
const testFunc = function() { return new Promise((resolve, reject) => { throw new Error('error'); }); }; async function testAsync() { try { await testFunc(); } catch (e) { console.log('能進來,說明異常能處理'); console.log(e); } } testAsync();
執行結果如下所示:
我們再看異步代碼,如下所示:
const testFunc = function() { setTimeout(() => { console.log(1111); return new Promise((resolve, reject) => { throw new Error('error'); }); }, 100); }; async function testAsync() { try { await testFunc(); } catch (e) { console.log('能進來,說明異常能處理'); console.log(e); } } testAsync();
如下圖所示:
2.6 process 方式(該方式既可以處理同步代碼的異常,也可以處理異步代碼的異常)。
如下同步代碼異常:
process.on('uncaughtException', (e) => { console.log('我能進來,說明可以處理異常'); console.log(e); }); function testFunc() { throw new Error('error'); } testFunc();
執行結果如下所示:
異步代碼如下所示:
process.on('uncaughtException', (e) => { console.log('我能進來,說明可以處理異常'); console.log(e); }); function testFunc() { setTimeout(() => { throw new Error('error'); }, 100); } testFunc();
如下圖所示:
2.7 domain 方式
domain也可以處理任何類型異常的信息,包含同步和異步。
如下同步代碼所示:
const domain = require('domain'); const d = domain.create(); d.on('error', (e) => { console.log('我能進來,說明能處理異常'); console.log(e); }); d.run(() => { throw new Error('同步代碼處理'); });
如下圖所示:
異步代碼如下所示:
const domain = require('domain'); const d = domain.create(); d.on('error', (e) => { console.log('我能進來,說明能處理異常'); console.log(e); }); d.run(() => { setTimeout(() => { throw new Error('異步代碼處理'); }, 100); });
如下圖所示: