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

[经验分享] Nodejs学习笔记(二)--- 事件模块

[复制链接]

尚未签到

发表于 2017-2-22 10:32:01 | 显示全部楼层 |阅读模式
目录




  • 简介及资料
  • 事件常用函数及使用

    • emitter.on(event, listener)
    • emitter.emit(event, [arg1], [arg2], [...])
    • emitter.once(event, listener)
    • emitter.removeListener(event, listener)
    • emitter.removeAllListeners([event])
    • emitter.listeners(event)
    • emitter.setMaxListeners(n)
    • 其它...



简介及资料
  http://nodejs.org/api/events.html
  http://www.infoq.com/cn/articles/tyq-nodejs-event

  events是node.js 最重要的模块,events模块只提供了一个对象events.EventEmitter,EventEmitter 的核心是事件发射与事件监听器。
  Node.js中大部分的模块,都继承自Event模块。
  与DOM树上事件不同,不存在事件冒泡、逐层捕获等行为。
  EventEmitter 支持若干个事件监听器。当事件发射时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。   

  如何访问:



require('events');
emitter.on(event, listener)
DSC0000.png



DSC0001.gif DSC0002.gif


/*
调用events模块,获取events.EventEmitter对象
*/
var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
/*
EventEmitter.on(event, listener) 为事件注册一个监听
参数1:event  字符串,事件名
参数2:回调函数
*/
ee.on('some_events', function(foo, bar) {
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
});
console.log('第一轮');
ee.emit('some_events', 'Wilson', 'Zhong');
console.log('第二轮');
ee.emit('some_events', 'Wilson', 'Z');
EventEmitter.on(event, listener) 示例源码
emitter.emit(event, [arg1], [arg2], [...])
DSC0003.png






var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
ee.on('some_events', function(foo, bar) {         
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
});
/*
EventEmitter.emit(event, [arg1], [arg2], [...])   触发指定事件
参数1:event  字符串,事件名
参数2:可选参数,按顺序传入回调函数的参数
返回值:该事件是否有监听
*/
var isSuccess = ee.emit('some_events', 'Wilson', 'Zhong');
ee.on('some_events', function(foo, bar) {         
console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar );
});
ee.emit('some_events', 'zhong', 'wei');
var isSuccess2 = ee.emit('other_events', 'Wilson', 'Zhong');
console.log(isSuccess);
console.log(isSuccess2);
emitter.emit(event, [arg1], [arg2], [...]) 示例源码
  示例进行了三次触发事件操作,其中some_events注册了监听,调用时emit函数会返回一个true,而other_events并没有注册监听,emit函数会返回一个false,表示该事件没有监听;当然也可以不用管这个返回值!


emitter.once(event, listener)
DSC0004.png






var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
/*
EventEmitter.once(event, listener)  为事件注册一次性监听,触发一次后移除监听
参数1:event  字符串,事件名
参数2:回调函数
*/
ee.once('some_events', function(foo, bar) {
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
});

console.log('第一轮');
ee.emit('some_events', 'Wilson', 'Zhong');
console.log('第二轮');
var isSuccess =  ee.emit('some_events', 'Wilson', 'Zhong');
console.log(isSuccess);
emitter.once(event, listener) 示例源码
  从上面示例代码执行结果可以看出,用emitter.once给some_events注册一个监听后,分两轮调用emitter.emit触发,第二轮会返回false;这表示用emitter.once注册监听和用前面讲的emitter.on注册监听略有不同,
  emitter.once注册监听是一次性监听,当触发一次后,会移除该监听!当然,从名字上就看就比较明显了^_^!


emitter.removeListener(event, listener)
  先来看一个失败的场景~~~
DSC0005.png






var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
ee.on('some_events', function(foo, bar) {
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
});
/*
看到API中removeListener移除方法时,以为应该是这样
但是结果^_^!!!!!
*/
ee.removeListener('some_events', function(){
console.log('成功移除事件some_events监听!');        
});
console.log('第一轮');
ee.emit('some_events', 'Wilson', 'Zhong');
emitter.removeListener(event, listener) 示例失败场景源码
  当我用emitter.on给some_events注册了一个监听后,我用emiiter.removeListener移除some_events的监听,随后再调用emitter.emit去触发,最后发现不是按我想像的在进行!为什么呢?
  我理所当然的认为emiiter.removeListener第二个参数是个回调函数,API还是要认真看清楚啊!!!

  下面再看个成功的场景~~~
   DSC0006.png





var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
var listener = function(foo,bar)
{
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
}
var listener2= function(foo,bar)
{
console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar );
}
var listener3= function(foo,bar)
{
console.log("第3个监听事件,参数foo=" + foo + ",bar="+bar );
}
ee.on('some_events', listener);
ee.on('some_events', listener2);
ee.on('some_events', listener3);
/*
EventEmitter.removeListener(event, listener)  移除指定事件的监听器
注意:该监听器必须是注册过的
PS:上一个例子之后以会失败,很大原因就是忽略了监听器,理所当然的认为传个事件名就OK了,所以就悲剧了!
*/
ee.removeListener('some_events', listener);
ee.removeListener('some_events', listener3);
ee.emit('some_events', 'Wilson', 'Zhong');
emitter.removeListener(event, listener) 示例成功场景源码
  我用示例中写法,给some_events添加了三个监听,又移除了第一个和第三个监听,最后再用emitter.emit触发some_events,输出结果不难发现,用emitter.removeListener移除的第一个和第三个监听都没有再起作用,
  想当然是害人地,原来emitter.removeListener的第二个参数是要移除的监听,而非移除成功后的回调函数……^_^!


emitter.removeAllListeners([event])
  emitter.removeListener用过了,但一个事件可以有多个监听,需要全部移除时,一个个移除明显不是愉快的做法,不符合偷懒的天性!
  让我们来体验一下emitter.removeAllListeners带来的便捷!
   DSC0007.png





var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
var listener = function(foo,bar)
{
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
}
var listener2= function(foo,bar)
{
console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar );
}
ee.on('some_events', listener);
ee.on('some_events', listener2);
ee.on('other_events',function(foo,bar)
{
console.log("其它监听事件,参数foo=" + foo + ",bar="+bar );
});
/*
EventEmitter.removeAllListeners([event])   移除(批定事件)所有监听器
参数1:可选参数,event  字符串,事件名
*/
ee.removeAllListeners('some_events');
ee.emit('some_events', 'Wilson', 'Zhong');
ee.emit('other_events', 'Wilson', 'Zhong');
emitter.removeAllListeners 传入事件名参数示例源码
  看看上面的执行结果,你会发现给some_events注册了两个监听;给other_events注册了一个监听;我调用emitter.removeAllListeners传了some_events事件名;
  最后使用emitter.on函数触发some_events和other_events两个事件,最后发现some_events注册的两个监听都不存在,而other_events注册的监听还存在;
  这表示当 emitter.removeAllListeners传用事件名作为参数时,为移除传入事件名的所有监听,而不会影响其它事件监听!

  emitter.removeAllListeners可以不传用事件名参数;直接执行
   DSC0008.png





var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
var listener = function(foo,bar)
{
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
}
var listener2= function(foo,bar)
{
console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar );
}
ee.on('some_events', listener);
ee.on('some_events', listener2);
ee.on('other_events',function(foo,bar)
{
console.log("其它监听事件,参数foo=" + foo + ",bar="+bar );
});
/*
EventEmitter.removeAllListeners([event])   移除(批定事件)所有监听器
参数1:可选参数,event  字符串,事件名
*/
ee.removeAllListeners();
ee.emit('some_events', 'Wilson', 'Zhong');
ee.emit('other_events', 'Wilson', 'Zhong');
emitter.removeAllListeners 不传参数示例源码
  示例代码和传入参数时几乎一样,只是在调用emitter.removeAllListeners并没有传入指定事件名;
  运行结果会发现some_events和other_events所有监听都不存在了,它会移除所有监听!(比较暴力的方法一般要慎用~~)


emitter.listeners(event)
DSC0009.png






var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
var listener = function(foo,bar)
{
console.log("第1个监听事件,参数foo=" + foo + ",bar="+bar );
}
var listener2= function(foo,bar)
{
console.log("第2个监听事件,参数foo=" + foo + ",bar="+bar );
}
ee.on('some_events', listener);
ee.on('some_events', listener2);
ee.on('other_events',function(foo,bar)
{
console.log("其它监听事件,参数foo=" + foo + ",bar="+bar );
});
/*
EventEmitter.listeners(event)   //返回指定事件的监听数组
参数1:event  字符串,事件名   
*/
var listenerEventsArr = ee.listeners('some_events');
console.log(listenerEventsArr.length)
for (var i = listenerEventsArr.length - 1; i >= 0; i--) {
console.log(listenerEventsArr);
};
emitter.listeners(event) 示例源码
  给some_events注册两个监听,调用emitter.listeners函数,传入some_events事件名,接收函数返回值;
  从结果可以看出,返回值接收到some_events所有注册监听的集合!


emitter.setMaxListeners(n)
  一个事件可以添加多个监听是没错,但Nodejs默认最大值是多少呢?
DSC00010.png






var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
/*
给EventEmitter 添加11个监听
*/
for (var i = 10; i >= 0; i--) {
ee.on('some_events',function()
{
console.log('第'+ (i +1) +'个监听');
});
};
添加N个监听示例源码
  上面示例中我用个循环给some_events添加11个监听,执行代码,发现warning信息出现,并且提示的比较详细了,需要用emitter.setMaxListeners()去提升限值

DSC00011.png






var EventEmitter = require('events').EventEmitter;   
var ee = new EventEmitter();
/*
EventEmitter.setMaxListeners (n)   给EventEmitter设置最大监听
参数1: n 数字类型,最大监听数
超过10个监听时,不设置EventEmitter的最大监听数会提示:
(node) warning: possible EventEmitter memory leak detected. 11 listeners added.
Use emitter.setMaxListeners() to increase limit.
设计者认为侦听器太多,可能导致内存泄漏,所以存在这样一个警告
*/
ee.setMaxListeners(15);
/*
给EventEmitter 添加11个监听
*/
for (var i = 10; i >= 0; i--) {
ee.on('some_events',function()
{
console.log('第'+ (i +1) +'个监听');
});
};
emitter.setMaxListeners 示例源码
  当我调用emitter.setMaxListeners传入15时,执行代码,warning信息不再出现;
  emitter.setMaxListeners的作用是给EventEmitter设置最大监听数,感觉一般是不需要设置这个值,10个还不够用的情况应该是比较少了!
  设计者认为侦听器太多会导致内存泄漏,所有就给出了一个警告!


其它...
  用的比较少的就不详细说了
  EventEmitter.defaultMaxListeners

  EventEmitter.defaultMaxListeners功能与setMaxListeners类似,
给所有EventEmitter设置最大监听
setMaxListeners优先级大于defaultMaxListeners

  EventEmitter.listenerCount(emitter, event)

  返回指定事件的监听数

  特殊的事件Error

  引用自Node.js开发指南:EventEmitter 定义了一个特殊的事件 error,它包含了“错误”的语义,我们在遇到 异常的时候通常会发射 error 事件。当 error 被发射时,EventEmitter 规定如果没有响 应的监听器,Node.js 会把它当作异常,退出程序并打印调用栈。我们一般要为会发射 error 事件的对象设置监听器,避免遇到错误后整个程序崩溃。

  事件的继承

  以后归到util里再讲一下吧,有兴趣的可以自已看看 http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor


运维网声明 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-345594-1-1.html 上篇帖子: 【社工】NodeJS 应用仓库钓鱼 下篇帖子: [NodeJS] 优缺点及适用场景讨论
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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