node.JS事件机制与events事件模块的使用方法详解


Posted in Javascript onFebruary 06, 2020

node.JS事件机制说明

多数 Node.js 核心 API 都是采用惯用的异步事件驱动架构,其中某些类型的对象(称为触发器)会周期性地触发命名事件来调用函数对象(监听器)。例如,一个net.Server对象会在每次有新连接时触发一个事件;一个 fs.ReadStream 会在文件被打开时触发一个事件;一个 stream会在数据可读时触发事件。

EventEmitter

EventEmitter 类由 events 模块定义和开放的,所有能触发事件的对象都是 EventEmitter 类的实例

var EventEmitter = require('events');
/*
{ [Function: EventEmitter]
 EventEmitter: [Circular],
 usingDomains: false,
 defaultMaxListeners: [Getter/Setter],
 init: [Function],
 listenerCount: [Function] }
 */
console.log(EventEmitter);

events模块的EventEmitter属性指向该模块本身

var events = require('events');
console.log(events.EventEmitter === events);//true
EventEmitter是一个构造函数,可以用来生成事件发生器的实例emitter
var EventEmitter = require('events');
var emitter = new EventEmitter();
/*
EventEmitter {
 domain: null,
 _events: {},
 _eventsCount: 0,
 _maxListeners: undefined }
 */
console.log(emitter);

方法

emitter.emit(eventName[, ...args])

eventName <any>

...args <any>

该方法按监听器的注册顺序,同步地调用每个注册到名为eventName事件的监听器,并传入提供的参数。如果事件有监听器,则返回true,否则返回false

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test1',function(){});
console.log(emitter.emit('test1'));//true
console.log(emitter.emit('test2'));//false

emitter.on(eventName, listener)

该方法用于添加listener函数到名为eventName的事件的监听器数组的末尾

eventName <any> 事件名

listener <Function> 回调函数

[注意]不会检查listener是否已被添加。多次调用并传入相同的eventName和listener会导致listener被添加与调用多次

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test',function(){
  console.log(1);
});
emitter.on('test',function(){
  console.log(2);
});
emitter.emit('test');//1 2

该方法返回一个 EventEmitter 引用,可以链式调用

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test',function(){
  console.log(1);
}).on('test',function(){
  console.log(2);
});
emitter.emit('test');//1 2

emitter.addListener(eventName, listener)

emitter.on(eventName, listener) 的别名

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.addListener('test',function(){
  console.log(1);
});
emitter.emit('test');//1

emitter.prependListener()

与on()方法不同,prependListener()方法可用于将事件监听器添加到监听器数组的开头

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test',function(){
  console.log(1);
}).prependListener('test',function(){
  console.log(2);
});
emitter.emit('test');//2 1

emitter.once(eventName, listener)

该方法添加一个单次 listener 函数到名为 eventName 的事件。 下次触发 eventName 事件时,监听器会被移除,然后调用

eventName <any> 事件名

listener <Function> 回调函数

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test',function(){
  console.log(1);
}).once('test',function(){
  console.log(2);
});
emitter.emit('test');//1 2
emitter.emit('test');//1

emitter.prependOnceListener()

该方法用于将事件监听器添加到监听器数组开头。下次触发eventName事件时,监听器会被移除,然后调用

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test',function(){
  console.log(1);
}).prependOnceListener('test',function(){
  console.log(2);
});
emitter.emit('test');//2 1
emitter.emit('test');//1

emitter.removeAllListeners([eventName])

eventName <any>

移除全部或指定 eventName 的监听器,返回一个 EventEmitter 引用,可以链式调用

[注意]在代码中移除其他地方添加的监听器是一个不好的做法,尤其是当 EventEmitter 实例是其他组件或模块(如 socket 或文件流)创建的

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test',function(){
  console.log(1);
}).removeAllListeners('test');
emitter.emit('test');//''

emitter.removeListener(eventName, listener)

eventName <any>

listener <Function>

从名为 eventName 的事件的监听器数组中移除指定的 listener

var EventEmitter = require('events');
var emitter = new EventEmitter();
function show(){
  console.log(1);
}
emitter.on('test',show).removeListener('test',show);
emitter.emit('test');//''

[注意]removeListener最多只会从监听器数组里移除一个监听器实例。如果任何单一的监听器被多次添加到指定eventName的监听器数组中,则必须多次调用removeListener才能移除每个实例

var EventEmitter = require('events');
var emitter = new EventEmitter();
function show(){
  console.log(1);
}
emitter.on('test',show).on('test',show).removeListener('test',show);
emitter.emit('test');//'1'

[注意]一旦一个事件被触发,所有绑定到它的监听器都会按顺序依次触发。这意味着,在事件触发后、最后一个监听器完成执行前,任何 removeListener() 或 removeAllListeners() 调用都不会从 emit() 中移除它们。 随后的事件会像预期的那样发生

因为监听器是使用内部数组进行管理的,所以调用它会改变在监听器被移除后注册的任何监听器的位置索引。 虽然这不会影响监听器的调用顺序,但意味着由 emitter.listeners() 方法返回的监听器数组副本需要被重新创建

var EventEmitter = require('events');
var emitter = new EventEmitter();
function show1(){
  console.log(1);
  emitter.removeListener('test',show2);
}
function show2(){
  console.log(2);
}
emitter.on('test',show1).on('test',show2);
emitter.emit('test');//1 2
emitter.emit('test');//1

设置

emitter.eventNames()

返回一个列出触发器已注册监听器的事件的数组。 数组中的值为字符串或符号

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.addListener('test1',function(){console.log(1);});
emitter.addListener('test2',function(){console.log(2);});
console.log(emitter.eventNames());//[ 'test1', 'test2' ]

emitter.listenerCount(eventName)

eventName <any> 正在被监听的事件名

返回正在监听名为 eventName 的事件的监听器的数量

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.addListener('test',function(){console.log(1);});
emitter.addListener('test',function(){console.log(1);});
console.log(emitter.listenerCount('test'));//2

emitter.listeners(eventName)

eventName <any>

返回名为 eventName 的事件的监听器数组的副本

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.addListener('test',function(){console.log(1);});
emitter.addListener('test',function(){console.log(2);});
console.log(emitter.listeners('test'));//[ [Function], [Function] ]
emitter.listeners('test')[0]();//1

emitter.getMaxListeners()

返回 EventEmitter 当前的最大监听器限制值

var EventEmitter = require('events');
var emitter = new EventEmitter();
console.log(emitter.getMaxListeners());//10

emitter.setMaxListeners(n)

默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 此限制有助于寻找内存泄露。 但是,并不是所有的事件都要被限为 10 个。 emitter.setMaxListeners() 方法允许修改指定的 EventEmitter 实例的限制。 值设为 Infinity(或 0)表明不限制监听器的数量。返回一个 EventEmitter 引用,可以链式调用

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){});
/*
Warning: Possible EventEmitter memory leak detected. 11 a listeners added. Use emitter.setMaxListeners() to increase limit
 */
var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.setMaxListeners(11);
emitter.on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){});

EventEmitter.defaultMaxListeners

每个事件默认可以注册最多10个监听器。单个EventEmitter实例的限制可以使用emitter.setMaxListeners(n)方法改变。所有EventEmitter实例的默认值可以使用EventEmitter.defaultMaxListeners属性改变

[注意]设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有EventEmitter 实例,包括之前创建的。因而,调用 emitter.setMaxListeners(n) 优先于 EventEmitter.defaultMaxListeners

var EventEmitter = require('events');
var emitter = new EventEmitter();
EventEmitter.defaultMaxListeners = 11;
emitter.on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){}).on('a',function(){});

node.JS事件注册与删除

'newListener' 事件

eventName <any> 要监听的事件的名称

listener <Function> 事件的句柄函数

EventEmitter 实例会在一个监听器被添加到其内部监听器数组之前触发自身的 'newListener' 事件

注册了 'newListener' 事件的监听器会传入事件名与被添加的监听器的引用。事实上,在添加监听器之前触发事件有一个微妙但重要的副作用: 'newListener' 回调中任何额外的被注册到相同名称的监听器会在监听器被添加之前被插入 

var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('newListener',function(){
  console.log(2);
})
emitter.on('test',function(){
  console.log(1);
})
emitter.emit('test');//2 1
var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test',function(){
  console.log(1);
})
emitter.on('newListener',function(){
  console.log(2);
})
emitter.emit('test');//1

'removeListener' 事件

eventName <any> 事件名

listener <Function> 事件句柄函数

'removeListener' 事件在 listener 被移除后触发

var EventEmitter = require('events');
var emitter = new EventEmitter();
function show(){
  console.log(1);
}
emitter.on('removeListener',function(){
  console.log(2);//2
})
emitter.on('test',show).removeListener('test',show);
var EventEmitter = require('events');
var emitter = new EventEmitter();
function show(){
  console.log(1);
}
emitter.on('test',show).removeListener('test',show);
emitter.on('removeListener',function(){
  console.log(2);//''
})
var EventEmitter = require('events');
var emitter = new EventEmitter();
function show(){
  console.log(1);
}
emitter.removeListener('test',show);
emitter.on('removeListener',function(){
  console.log(2);//''

更多关于node.js事件的相关文章大家可以点击下面的相关链接

Javascript 相关文章推荐
Jqyery中同等与js中windows.onload的应用
May 10 Javascript
jQuery实现鼠标经过事件的延时处理效果
Aug 20 Javascript
AngualrJS中的Directive制作一个菜单
Jan 26 Javascript
基于JS模仿windows文件按名称排序效果
Jun 29 Javascript
深入浅析JavaScript中的Function类型
Jul 09 Javascript
几句话带你理解JS中的this、闭包、原型链
Sep 26 Javascript
Form表单按回车自动提交表单的实现方法
Nov 18 Javascript
微信小程序 MD5加密登录密码详解及实例代码
Jan 12 Javascript
微信小程序 页面传值详解
Mar 10 Javascript
JavaScript实现滑动导航栏效果
Aug 30 Javascript
浅谈angularJS2中的界面跳转方法
Aug 31 Javascript
Vue解析剪切板图片并实现发送功能
Feb 04 Javascript
如何通过javaScript去除字符串两端的空白字符
Feb 06 #Javascript
ckeditor一键排版功能实现方法分析
Feb 06 #Javascript
JavaScript如何判断input数据类型
Feb 06 #Javascript
如何使用Jquery动态生成二级选项列表
Feb 06 #jQuery
CKEditor扩展插件:自动排版功能autoformat插件实现方法详解
Feb 06 #Javascript
JS实现盒子拖拽效果
Feb 06 #Javascript
JavaScript实现拖拽盒子效果
Feb 06 #Javascript
You might like
thinkPHP简单实现多个子查询语句的方法
2016/12/05 PHP
Javascript入门学习资料收集整理篇
2008/07/06 Javascript
jQuery 性能优化手册 推荐
2010/02/23 Javascript
游览器中javascript的执行过程(图文)
2012/05/20 Javascript
jquery移动listbox的值原理及代码
2013/05/03 Javascript
jquery与prototype框架的详细对比
2013/11/21 Javascript
js通过元素class名字获取元素集合的具体实现
2014/01/06 Javascript
js换图片效果可进行定时操作
2014/06/09 Javascript
JS按回车键实现登录的方法
2014/08/25 Javascript
基于replaceChild制作简单的吞噬特效
2015/09/21 Javascript
学习JavaScript设计模式(代理模式)
2015/12/03 Javascript
JavaScript基础教程——入门必看篇
2016/05/20 Javascript
简单分析javascript中的函数
2016/09/10 Javascript
js获取腾讯视频ID的方法
2016/10/03 Javascript
BootStrap modal模态弹窗使用小结
2016/10/26 Javascript
JavaScript设计模式之建造者模式实例教程
2018/07/02 Javascript
解决Layui 表单提交数据为空的问题
2018/08/15 Javascript
uni-app 自定义底部导航栏的实现
2020/12/11 Javascript
[57:36]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第三场 2月1日
2021/03/11 DOTA
简介二分查找算法与相关的Python实现示例
2015/08/26 Python
Python使用os.listdir()和os.walk()获取文件路径与文件下所有目录的方法
2019/04/01 Python
一文了解Python并发编程的工程实现方法
2019/05/31 Python
用Python+OpenCV对比图像质量的几种方法
2019/07/15 Python
Python定时任务随机时间执行的实现方法
2019/08/14 Python
关于初始种子自动选取的区域生长实例(python+opencv)
2020/01/16 Python
Python调用Windows命令打印文件
2020/02/07 Python
python 安装impala包步骤
2020/03/28 Python
三下乡活动方案
2014/01/31 职场文书
《在家里》教后反思
2014/03/01 职场文书
国际金融专业自荐信
2014/07/05 职场文书
群众路线教育实践活动学习笔记
2014/11/05 职场文书
2014年教育实习工作总结
2014/11/22 职场文书
英文慰问信范文
2015/03/24 职场文书
2016教师学习教育法心得体会
2016/01/19 职场文书
如何书写民事调解协议书?
2019/06/25 职场文书
php png失真的原因及解决办法
2021/11/17 PHP