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 相关文章推荐
DOM Scripting中的图片切换[兼容Firefox]
Jun 12 Javascript
玩转jQuery按钮 请告诉我你最喜欢哪些?
Jan 08 Javascript
js中创建对象的几种方式示例介绍
Jan 26 Javascript
整理AngularJS框架使用过程当中的一些性能优化要点
Mar 05 Javascript
Jquery和Js获得元素标签名称的方法总结
Oct 08 Javascript
Vue.js系列之项目搭建(1)
Jan 03 Javascript
jQuery阻止移动端遮罩层后页面滚动
Mar 15 Javascript
JS实现简单的天数计算器完整实例
Apr 28 Javascript
JS实现简单短信验证码界面
Aug 07 Javascript
node.js多个异步过程中判断执行是否完成的解决方案
Dec 10 Javascript
JS 实现微信扫一扫功能
Sep 14 Javascript
Vue时间轴 vue-light-timeline的用法说明
Oct 29 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
php获取字符串中各个字符出现次数的方法
2015/02/23 PHP
高性能Javascript笔记 数据的存储与访问性能优化
2012/08/02 Javascript
在js(jquery)中获得文本框焦点和失去焦点的方法
2012/12/04 Javascript
jquery自动切换tabs选项卡的具体实现
2013/12/24 Javascript
javascript中的取反再取反~~没有意义
2014/04/06 Javascript
js的参数有长度限制吗?发现不能超过2083个字符
2014/04/20 Javascript
借助JavaScript脚本判断浏览器Flash Player信息的方法
2014/07/09 Javascript
Javascript与jQuery方法的隐藏与显示
2015/01/19 Javascript
javascript实现在线客服效果
2015/07/15 Javascript
Vue.js常用指令汇总(v-if、v-for等)
2016/11/03 Javascript
原生js实现淘宝购物车功能
2020/06/23 Javascript
jQuery中用on绑定事件时需注意的事项
2017/03/19 Javascript
BootStrap daterangepicker 双日历控件
2017/06/02 Javascript
Angular中ng-options下拉数据默认值的设定方法
2017/06/21 Javascript
浅谈angularJS2中的界面跳转方法
2018/08/31 Javascript
JavaScript使用localStorage存储数据
2019/09/25 Javascript
javascript设计模式 ? 代理模式原理与用法实例分析
2020/04/16 Javascript
[00:17]DOTA2荣耀之路5:It’s a disastah!
2018/05/28 DOTA
Python中类的定义、继承及使用对象实例详解
2015/04/30 Python
浅谈python字典多键值及重复键值的使用
2016/11/04 Python
django+mysql的使用示例
2018/11/23 Python
浅谈python中真正关闭socket的方法
2018/12/18 Python
DataFrame:通过SparkSql将scala类转为DataFrame的方法
2019/01/29 Python
Python 虚拟空间的使用代码详解
2019/06/10 Python
python将字典列表导出为Excel文件的方法
2019/09/02 Python
python中可以声明变量类型吗
2020/06/18 Python
安装pyinstaller遇到的各种问题(小结)
2020/11/20 Python
css3 border-radius属性详解
2017/07/05 HTML / CSS
用canvas显示验证码的实现
2020/04/10 HTML / CSS
Boden澳大利亚官网:英国在线服装公司
2018/08/05 全球购物
俄罗斯连接商品和买家的在线平台:goods.ru
2020/11/30 全球购物
探亲邀请信范文
2014/01/30 职场文书
家长会标语
2014/06/24 职场文书
2014年幼儿园园务工作总结
2014/12/05 职场文书
宝葫芦的秘密观后感
2015/06/11 职场文书
openEuler 搭建java开发环境的详细过程
2022/06/10 Servers