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 相关文章推荐
利用ASP发送和接收XML数据的处理方法与代码
Nov 13 Javascript
jquery 全局AJAX事件使用代码
Nov 05 Javascript
分享一个我自己写的ToolTip提示插件(附源码)
Jan 20 Javascript
简单的jQuery banner图片轮播实例代码
Mar 04 Javascript
微信小程序 免费SSL证书https、TLS版本问题的解决办法
Dec 14 Javascript
js实现本地图片文件拖拽效果
Jul 18 Javascript
Nuxt.js实战详解
Jan 18 Javascript
VUE 配置vue-devtools调试工具及安装方法
Sep 30 Javascript
详解小程序退出页面时清除定时器
Apr 28 Javascript
基于Vue SEO的四种方案(小结)
Jul 01 Javascript
vue 开发之路由配置方法详解
Dec 02 Javascript
JavaScript高级程序设计之基本引用类型
Nov 17 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删除特定数组内容并且重建数组索引的方法.
2011/03/25 PHP
destoon在360浏览器下出现用户被强行注销的解决方法
2014/06/26 PHP
PHP实现获取图片颜色值的方法
2014/07/11 PHP
php设计模式之简单工厂模式详解
2014/09/04 PHP
php微信开发之自定义菜单实现
2016/11/18 PHP
详解ThinkPHP3.2.3验证码显示、刷新、校验
2016/12/29 PHP
Windows 下安装 swoole 图文教程(php)
2017/06/05 PHP
使用PHP反射机制来构造&quot;CREATE TABLE&quot;的sql语句
2019/03/21 PHP
学习YUI.Ext第七日-View&amp;JSONView Part Two-一个画室网站的案例
2007/03/10 Javascript
innertext , insertadjacentelement , insertadjacenthtml , insertadjacenttext 等区别
2007/06/29 Javascript
锋利的jQuery 要点归纳(二) jQuery中的DOM操作(下)
2010/03/23 Javascript
jQuery中读取json文件示例代码
2013/05/10 Javascript
js数组去重的hash方法
2016/12/22 Javascript
webpack打包node.js后端项目的方法
2018/03/10 Javascript
Node 升级到最新稳定版的方法分享
2018/05/17 Javascript
Element实现表格分页数据选择+全选所有完善批量操作
2019/06/07 Javascript
使用p5.js实现动态GIF图片临摹重现
2019/10/23 Javascript
解决Vue大括号字符换行踩的坑
2020/11/09 Javascript
Python实现SMTP发送邮件详细教程
2021/03/02 Python
Python实现视频下载功能
2017/03/14 Python
python用户管理系统
2018/03/13 Python
python模式 工厂模式原理及实例详解
2020/02/11 Python
django rest framework 过滤时间操作
2020/07/12 Python
详解Pycharm安装及Django安装配置指南
2020/09/15 Python
基于Python实现粒子滤波效果
2020/12/01 Python
CSS3 按钮边框动画的实现
2020/11/12 HTML / CSS
W3C公布最新的HTML5标准草案
2008/10/17 HTML / CSS
移动端Html5页面生成图片解决方案
2018/08/07 HTML / CSS
优秀员工评语
2014/02/10 职场文书
材料专业毕业生求职信
2014/02/26 职场文书
《放飞蜻蜓》教学反思
2014/04/27 职场文书
病危通知单
2015/04/17 职场文书
浅谈JS的二进制家族
2021/05/09 Javascript
Go语言实现Base64、Base58编码与解码
2021/07/26 Golang
一次项目中Thinkphp绕过禁用函数的实战记录
2021/11/17 PHP
javascript中Set、Map、WeakSet、WeakMap区别
2022/12/24 Javascript