用domain模块进行Node.js异步异常捕获处理

 2015年06月28日    880     声明


对于一般的错误可以用try catch进行异常捕捉处理,但是try catch无法捕捉到Node.js异步回调函数中的异常,这会对程序的健壮性造成一定影响,回调函数中的异常可能导致Node进程的结束。对于回调函数中的异常,可以使用Node.js的domain模块进行捕捉处理。注册到domain中的事件组,在出现错误或抛出异常时,会被通知到domain对象中而不是直接被process.on('uncaughtException')处理,因此也不会导致进程退出。


1. try catch不能处理的异步异常

对于如下一个异步异常,try catch无法捕捉,虽然最终会被传递到全局对象processprocess.on('uncaughtException')事件临听中,但进程还是会退出。

//抛出一个异步异常
function callbackError() {
    setTimeout(function(){
        throw new Error("一个异步异常");
    }, 1)
}

try {
    callbackError();
} catch (err) {
    console.log(err);
}

process.on('uncaughtException', function (err) {
    console.log(err);
});

运行后,输出如下:

[Error: 一个异步异常]


2. 用domain捕获异步异常

使用domain模块进行异常处理时,domain对象会把不同的IO的操作做为一个事件数组,将事件事件和回调注册到domain对象中。当被注册的事件发生错误或抛出异常时,domain对象实例会得到通知,因此不会丢失运行时环境,错误不会被传递到process.on('uncaughtException')事件监听中,也就不会导致程序进程的退出。

使用domain模块需要require('domain')引用。使用domain模块进行异常处理,示例如下:

var domain = require('domain');

//抛出一个异步异常
function callbackError() {
    setTimeout(function(){
        throw new Error("一个异步异常");
    }, 10)
}

var d = domain.create();
d.on('error',function(err){
    console.log(err);
});

d.run(callbackError);

运行后,输出如下:

{ [Error: 一个异步异常]
  domain: 
   { domain: null,
     _events: { error: [Function] },
     _maxListeners: 10,
     members: [] },
  domainThrown: true }

在上述示例中,create()方法会返回一个domain对象,与createDomain()方法一样,都是调用Domain类构造函数返回一个对象实例。run()方法会在domain上下文中执行一个函数,并隐式绑定所有事件监听,定时器和低级的请求。与process.on('uncaughtException')不同,domain中的异常最终是被d.on('error')事件监听处理,而非进程退出。