设为首页 收藏本站
查看: 1172|回复: 0

[经验分享] 一起读nodejs(八)----域(domain)

[复制链接]
YunVN网友  发表于 2017-2-22 07:31:07 |阅读模式
    本文是对nodejs0.8.9版本的api开发手册解读.nodejs网址
  
    域(Domain)
    stability:1 - experimental
    域提供了一种简单把多个不同的io操作看作一个单独的组的方法.如果任何一个事件发射器或者已在域中注册的回调函数发出了一个error事件,或者抛出一个error错误信息,域将会被通知,而不是在process.on('caughtException')处理函数一样丢失上下文,或者用一个code引起程序退出.(有点像数据库的事物的样子)
    这是在node0.8版本中新增加的特性.这是它第一次亮相,其他它能在未来有更重要的作用.请使用它,并提供使用反馈.
    由于它的试验性质,域的特性只有在domain模块加载一次以后才会生效.没有域是默认被创建或者注册的.这是故意设计成这样的,为了避免在现在的程序中产生一些不利的影响.在未来node的版本中期待改成默认启用.
  

   错误对象的补充(additions to Error objects)
    任何时候一个error对象被路由传递到一个domain(域看着别扭)中时,需要添加一些额外的字段到error对象上.


  • error.domainThe domain that first handled the error.第一次处理error的domain对象
  • error.domain_emitterThe event emitter that emitted an 'error' event with the error object.发出error事件的对象.
  • error.domain_boundThe callback function which was bound to the domain, and passed an error as its first
    argument.绑定到domain上的callback,callback的第一个参数需要指定为error.
  • error.domain_thrownA boolean indicating whether the error was thrown, emitted, or passed to a bound callback
    function.一个boolean对象,指定这个error对象是被抛出的还是发出的,或者传到到domain 绑定的callback中.
    当一个EventEmitter遇到一个错误时,典型的动作时发出一个error事件.在node里面,error事件将会被作为特殊情况处理,如果没有相应的监听函数,默认的动作是打印堆栈信息,然后退出程序.
    当所有的EventEmitter对象在添加新的监听函数时都会发出newListener事件.
    
隐式绑定(Implicit Binding)

    如果domain被启用的,那么所有的新的EventEmitter对象(包括:Stream对象,request对象,response对象等等)都将会在他们被创建的时候隐式的绑定到这个激活的domain上.
    此外,传递给低级别的事件循环请求(例如:fs.open,或者的callback-taking方法)将会自动的绑定到激活的domain上.如果他们抛出异常,domain会捕获错误信息.
    为了避免使用过多的内存,domain对象不会被隐式的添加为当前激活的domain的子对象.如果他们存在,这将不容易阻止request和response对象成为合适的垃圾收集对象.
    如果你需要内嵌一个domain对象到一个父domain对象中,你必须明确的添加他们,并且稍后调用dispose()方法(dispose是销毁domain对象,稍后有介绍).
    隐式绑定路由跑出错误信息和error事件到domain的error事件中.但是不会在domain对象上注册事件触发器,所以domain.dispose()不会关闭事件触发器.隐式绑定只是处理抛出的错误信息和error事件.
  

    显示绑定(Explicit binding)
    有时,domain对象不应该被当成一个指定事件的事件发射器(Emitter)来使用.或者,事件发射器已经在一个domain中的环境变量中被创建,但是应该被绑定到其他domain上.
    例如这里有一个http服务器的domain对象,但是我们想在每个request上使用一个单独的domain.
    通过显示绑定就有可能实现.
    例如:

// create a top-level domain for the server
var serverDomain = domain.create();
serverDomain.run(function() {
// server is created in the scope of serverDomain
http.createServer(function(req, res) {
// req and res are also created in the scope of serverDomain
// however, we'd prefer to have a separate domain for each request.
// create it first thing, and add req and res to it.
var reqd = domain.create();
reqd.add(req);
reqd.add(res);
reqd.on('error', function(er) {
console.error('Error', er, req.url);
try {
res.writeHead(500);
res.end('Error occurred, sorry.');
res.on('close', function() {
// forcibly shut down any other things added to this domain
reqd.dispose();
});
} catch (er) {
console.error('Error sending 500', er, req.url);
// tried our best.  clean up anything remaining.
reqd.dispose();
}
});
}).listen(1337);
});
  


    domain.create()


  • return:Domain

  返回一个新的domain对象.
  


    Class:Domain

  domain类封装了路由error和uncaught 异常到基于的domain中.

  domain类是EventEmitter的一个子类,如果想要处理domain捕获的错误信息,可以监听error事件.
  


    domain.run(fn)


  • fnFunction



  在domain的上下文中运行提供的function,隐式绑定所有的事件触发器,定时器,和在domain上下文中创建的低级的requests.

  这是使用domain最基本的一种方式.

  例子:
var d = domain.create();
d.on('error', function(er) {
console.error('Caught error!', er);
});
d.run(function() {
process.nextTick(function() {
setTimeout(function() { // simulating some various async stuff
fs.open('non-existent file', 'r', function(er, fd) {
if (er) throw er;
// proceed...
});
}, 100);
});
});


  在这个例子中,do.on('error')处理器将会被触发,而不是程序挂掉.(在不使用domain的情况下,遇见未捕获的异常或者抛出error事件会导致程序死掉.)



    domain.members


  • Array



  显示绑定到domain中的定时器和事件触发器的数组.




    domain.add(emitter)


  • event Emitter|timer Emitter|timer to be added to the domain. 事件触发器或者定时器触发器或者定时器被添加到domain中.



  显式的添加一个触发器到domain中.当事件触发器抛出一个错误时任何一个事件处理函数被调用时,或者这个事件触发器发出一个error时,他们都将会被路由到domain的error事件中,就像隐式绑定一样.

  当定时器从setInterval或者setTimeout返回时也将这样操作.如果他们的回调函数抛出异常时,将会被domain的error事件处理函数所捕获.

  如果定时器或者事件触发器已经绑定到了domain中,node会将他们从原先的domain中移除,并且添加到当前的domain中.



    domain.remove(emitter)


  • event Emitter|timer Emitter|timer to be added to the domain. 事件触发器或者定时器触发器或者定时器被从domain中移除.



  和domain.add(emitter)相反,这个方法是从指定的触发器上移除domain的处理操作.



  


    domain.bind(cb)


  • cb function 回调函数.
  • return:function,绑定后的函数.



  返回的函数,将是一个包裹了所提供的回调函数的函数.当这个返回的函数被调用,抛出的任何错误都将会被路由到domain的error事件中.
var d = domain.create();
function readSomeFile(filename, cb) {
fs.readFile(filename, 'utf8', d.bind(function(er, data) {
// if this throws, it will also be passed to the domain
return cb(er, data ? JSON.parse(data) : null);
}));
}
d.on('error', function(er) {
// an error occurred somewhere.
// if we throw it now, it will crash the program
// with the normal line number and stack message.
});



    domain.intercept(cb)


  • cb function 回调函数.
  • return:function,被拦截的函数.



  这个方法几乎和domain.bind(cb)方法一样.然而,除了会捕获抛出的错误信息之外,将会拦截error对象,并当作需要返回的函数的第一个参数.

  这样一来,比较常见的:if(er)return cb(er)这种方式就可以被取代,你只需要单独的在一个错误处理handler里面处理所有的error信息了.
  
  例子:

var d = domain.create();
function readSomeFile(filename, cb) {
fs.readFile(filename, 'utf8', d.intercept(function(data) {
//也就是说只要使用了d.intercept()方法包裹的回调函数,如果他们发生错误或者发出error事件,都会被统一的下面的d.on('error',fn)所处理.这种情况和domain.run的区别是domain.run是需要所有的把所有东西都放在一个domain里面,才能拦截domain的对象的事件.而domain.intercept(),你想包裹哪一个回调函数都行.可以对异常类型进行全局处理.
// note, the first argument is never passed to the
// callback since it is assumed to be the 'Error' argument
// and thus intercepted by the domain.
// if this throws, it will also be passed to the domain
// so the error-handling logic can be moved to the 'error'
// event on the domain instead of being repeated throughout
// the program.
return cb(null, JSON.parse(data));
}));
}
d.on('error', function(er) {
// an error occurred somewhere.
// if we throw it now, it will crash the program
// with the normal line number and stack message.
});
  


  

domain.dispose()

    dispose方法用来销毁一个domain对象,并且在清空任何一个和所有io和这个domain有关联的对象或事件时,努力做到最好.流(Streams)可以被终止,结束,关闭,并且/或者 销毁.定时器是被清除.显示绑定的回调函数不会在会调用.任何一个从domain中出现的error事件也会被忽略.
    调用dispose的意图通常是为了当domain的环境变量被发现在一个错误的状态时避免发生级联错误.
    一旦domain被disposed掉,dispose事件将会发出.
    注意:io操作可能还会继续执行.然而,为了达到最大限度的可能性,一旦一个domain被disposed,在domain中的发射器集合中产生的或者发出的错误信息将会被忽略.所以,甚至如果一些剩下的动作依然在执行,node也不会在和他们有深层次的交流.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-345383-1-1.html 上篇帖子: 一起读nodejs(五)----进程(process) 下篇帖子: 基于NODEJS的前后端项目分离实践
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表