domain: node.js的异常捕获利器

众所周知,异常捕获是保障服务健壮性常用的手段,node.js也自然支持这一特性。但node.js异步、基于消息的编程方式给异常捕获带来一些困难,请看下面的例子:

process.on('uncaughtException', function(e) {
    console.log("exception in uncaughtException:", e);
});

try {
    process.nextTick(function () {
        throw new Error("exception in nextTick callback");
    });
} catch (e) {
    console.log("exception in 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) {
    console.log("error in domain:", e);
});

d.run(function () {
    process.nextTick(function () {
        throw new Error("exception in nextTick callback");
    });
});

输出:
error in domain: { [Error: exception in nextTick callback]
  domain_thrown: true,
  domain: { members: [], _events: { error: [Function] } } }

以上只是一个简单的例子,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) {
    console.log("error in domain:", e);
});

var e;
d.run(function () {
    e = new events.EventEmitter();
});

e.on('msg', function () {
    throw new Error("exception in msg callback");
});

e.emit('error', new Error("error msg"));
e.emit('msg');

输出:
error in domain: { [Error: error msg]
  domain_emitter: 
   { domain: { members: [], _events: [Object] },
     _events: { msg: [Function] } },
  domain: { members: [], _events: { error: [Function] } },
  domain_thrown: false }
error in domain: { [Error: exception in msg callback]
  domain_thrown: true,
  domain: { members: [], _events: { error: [Function] } } }

注意不是EventEmitter所有成员函数中的exception都可以被自动捕获,如果成员函数不是在事件响应函数中执行,并且未跟domain绑定,就不会被domain捕获。
示例:
var domain = require('domain');
var events = require('events');

var d = domain.create();
d.on('error', function(e) {
    console.log("error in domain:", e);
});

var e;
d.run(function () {
    e = new events.EventEmitter();
});

e.f = function () {
    throw new Error("exception in member function");
};
e.f();

如果在domain.run()中执行,或跟domain绑定,是可以被捕获的:
d.run(function () {
    e.f();
});

domain还有其他接口,用于绑定对象、函数等,请参考官方文档:
http://nodejs.org/api/domain.html

转帖:http://blog.sina.com.cn/s/blog_70000469010134wr.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值