正文
由于nodejs是非阻塞单进程单线程的,一旦nodejs抛出异常,整个服务就会停掉。服务将会非常不稳定。
错误异常有两种场景的出现,
一种是代码运行中throw new error没有被捕获
另一种是Promise的失败回调函数,没有对应的reject回调函数处理
针对这两种情况Nodejs都有默认的统一处理方式,就是给整个进程process对象监听相应的错误事件。
1  | process.on('uncaughtException',function(err){  | 
在有可能出现异常的地方,全部使用try { } catch(){ }进行嵌套。
注意
一般情况下,我们会将有可能出错的代码放到
try/catch块里。但是到了 Node.js,由于
try/catch无法捕捉异步回调里的异常,Node.js 原生提供uncaughtException事件挂到process对象上,用于捕获所有未处理的异常。
处理异常的方式
总的来说处理异常有两种方式
- 同步异常用
try/catch - 异步异常要用各自的处理方式
 
模拟异常
1  | // 每秒钟打印一次时间,确保程序没有奔溃  | 
同步异常
try catch 方式
1  | try {  | 
但是try catch方式无法处理异步代码块内出现的异常,你可以理解为执行catch时,异常还没有发生。
1  | try {  | 
异步异常
callback方式
1  | require("fs").mkdir('G://test', function (e) {  | 
event方式
1  | let events = require("events");  | 
Promise 方式
1  | new Promise((resolve, reject) => {  | 
或者
1  | new Promise((resolve, reject) => {  | 
Promise同样无法处理异步代码块中抛出的异常
1  | new Promise((resolve, reject) => {  | 
Async/Await 方式
Async是基于Promise的,可以用Await等待响应就可以用try/catch来捕获了。
1  | var sleep = function (time) {  | 
所有异常
process方式
process方式可以捕获任何异常(不管是同步代码块中的异常还是异步代码块中的异常)
1  | process.on('uncaughtException', function (e) {  | 
Promise未捕获
1  | process.on('unhandledRejection', function (err, promise) {  | 
Promise中的异步错误
1  | new Promise((resolve, reject) => {  | 
domain方式
官方不推荐使用
https://nodejs.org/api/domain.html
https://nodejs.org/zh-cn/docs/guides/domain-postmortem/
domain模块,把处理多个不同的IO的操作作为一个组。注册事件和回调到domain,当发生一个错误事件或抛出一个错误时,domain对象会被通知,不会丢失上下文环境,也不导致程序错误立即退出,与process.on('uncaughtException')不同。
Domain 模块可分为隐式绑定和显式绑定:
- 隐式绑定: 把在domain上下文中定义的变量,自动绑定到domain对象
 - 显式绑定: 把不是在domain上下文中定义的变量,以代码的方式绑定到domain对象
 
| 方法 & 描述 | |
|---|---|
| 1 | domain.create()  返回一个domain对象。  | 
| 2 | domain.run(function)  在域的上下文运行提供的函数,隐式的绑定了所有的事件分发器,计时器和底层请求。  | 
| 3 | domain.add(emitter)  显式的增加事件  | 
| 4 | domain.remove(emitter)  删除事件。  | 
| 5 | domain.bind(callback)  返回的函数是一个对于所提供的回调函数的包装函数。当调用这个返回的函数时,所有被抛出的错误都会被导向到这个域的 error 事件。  | 
| 6 | domain.intercept(callback)  和 domain.bind(callback) 类似。除了捕捉被抛出的错误外,它还会拦截 Error 对象作为参数传递到这个函数。  | 
| 7 | domain.enter()  进入一个异步调用的上下文,绑定到domain。  | 
| 8 | domain.exit()  退出当前的domain,切换到不同的链的异步调用的上下文中。对应domain.enter()。  | 
| 9 | domain.on(‘error’,function(err){}) 捕获的错误监听  | 
process方式虽然可以捕获任何类型的异常,但是process太过笨重,除了记录下错误信息,其他地方不适合使用,domain这个也可以处理任何类型异常的模块,显然是一个不错的选择。
1  | let domain = require('domain')  | 
或者
1  | let d = require('domain').create();  | 
express框架
express作为nodejs比较常用的框架,其实nodejs自己也有一定的异常错误捕获机制
1  | // Express errorHandler  |