众所周知,异常捕获是保障服务健壮性常用的手段,node.js也自然支持这一特性。但node.js异步、基于消息的编程方式给异常捕获带来一些困难,请看下面的例子:
process.on('uncaughtException', function(e) {
});
try {
} catch (e) {
}
输出:
exception in uncaughtException: [Error: exception in nextTick callback]
可见,try-catch不能捕获回调函数中的异常,也不能捕获事件响应函数中的异常。通常的解决办法是在这些函数中都加入try-catch,但副作用也很明显,一方面增加了代码复杂度和嵌套深度,降低了可读性和可维护性,另一方面v8对于try-catch中的代码优化作用会降低,即牺牲了性能。
node v0.8中新增了domain模块,大大简化异步开发中异常捕获的复杂度,引入domain的代码如下:
var domain = require('domain');
var d = domain.create();
d.on('error', function(e) {
});
d.run(function () {
});
输出:
error in domain: { [Error: exception in nextTick callback]
以上只是一个简单的例子,domain的初衷在于解决异步io的异常处理,只要是注册在domain中event emitters、timer、callback函数,其回调函数中产生的"error"事件和exception都可以被domain捕获。
来看示例:
var domain = require('domain');
var events = require('events');
var d = domain.create();
d.on('error', function(e) {
});
var e;
d.run(function () {
});
e.on('msg', function () {
});
e.emit('error', new Error("error msg"));
e.emit('msg');
输出:
error in domain: { [Error: error msg]
error in domain: { [Error: exception in msg callback]
注意不是EventEmitter所有成员函数中的exception都可以被自动捕获,如果成员函数不是在事件响应函数中执行,并且未跟domain绑定,就不会被domain捕获。
示例:
var domain = require('domain');
var events = require('events');
var d = domain.create();
d.on('error', function(e) {
});
var e;
d.run(function () {
});
e.f = function () {
};
e.f();
如果在domain.run()中执行,或跟domain绑定,是可以被捕获的:
d.run(function () {
});
domain还有其他接口,用于绑定对象、函数等,请参考官方文档:
http://nodejs.org/api/domain.html
转帖:http://blog.sina.com.cn/s/blog_70000469010134wr.html