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); });
如下图所示: