第7章 Node.js EventEmitter

Node.js 所有的异步I/O操作在完成是都会发送一个事件到事件队列。
Node.js 里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时触发一个事件,一个fs.resaStream对象会在文件被打开的时候触发一个事件。所有这些产生事件的对象都是events.EventEmitter的实例。

7-1EventEmitter类

events模块只提供了一个对象:events.EventEmitter。
EventEmitter的核心就是事件触发事件监听器功能的封装。
可以通过require('events')来访问该模块

//引入 events 模块
var events = require('events');

//创建eventEmitter对象
var eventEmitter  = new events.EventEmitter();

EventEmitter 对象如果在实例化时发生错误,会触发error事件。
当添加新的监听器时,newListener 事件会触发。
当监听器被移除时,removeListener事件会被触发。
下面咱们来看一个例子:

//event.js 文件
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event', function() {
  console.log('some_event 事件触发');
});
setTimeOut(function() {
  event.emit('some_event')
}, 1000);

执行结果:

node event.js

some_event 事件触发

运行这段代码,1秒后控制台输出了some_evnet 事件触发
其原理是event对象注册了事件some_event的一个监听器,
然后我们通过setTimeout在1秒后向event对象发送事件some_event,此时会调用some_event的监听器。

EventEmitter的每个事件有一个事件名若干个参数组成。
事件名:是一个字符串,有一定的语义化
对于每个事件,EventEmitter支持若干个事件监听器。
当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递
那么我们来看一个例子:

//event1.js
var events = require('events');
var emitter =  new events.EventEmitter();
emitter.on('someEvent',function(arg1,arg2){
  console.log('listener1',arg1,arg2)
});
emitter.on('someEvent',function(arg1,arg2){
  console.log('listener2',arg1,arg2)
});
emitter.emit('someEvent','参数1','参数2');

运行结果:

node event1.js
listener1 参数1 参数2
listener2 参数1 参数2

从上面这个例子来看:
emitter为事件someEvent注册了两个事件监听器,
然后出发了someEvent事件。
EventEmitter提供了多个属性,如onemit

  • on函数:用于绑定事件函数
  • emit:用于触发一个事件
    那么EventEmitter都有哪些属性呢?
7-2方法
1.addListener(event,listener)   //为指定事件添加一个监听器到监听器数组的尾部
2.on(event,listener) //为指定事件注册一个监听器,接受一个字符串event和一个回调函数
server.on('connection',function(stream){
  console.log('someone connected!');
})
3.once(event,listener) //未指定事件注册一个单次监听器,即 监听器最多只会触发一次,出发后立即解除该监听器
4.removeListener(event,listener) //移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器,它会接受两个参数,第一个是事件名称,第二个是回调函数名称
var callback = function(stream){
  console.log('someone connected')
}
server.on('connection',callback);
server.removeListener('connection',callback);
5.removeAllListener([event]) //移除所有事件的所有监听,如果指定事件,则移除该事件的所有监听
6.setMaxListener(n) //默认10个 设置数字可以提高监听器的默认限制数量
7.listeners(event) //返回指定事件的监听数组
8.emit(event,[arg1],[arg2],...) //按监听器的书序执行每个监听器,如果事件有注册监听返回true,否者返回false
7-3 类方法
1.listenerCount(emitter,event)  //返回指定事件的监听器数量
events.EventEmitter.listenerCount(emitter,eventName) //已废弃,不推荐
events.emitter.listenerCount(eventName) //推荐
7-4 事件
1.newListener //该事件在添加新监听器时被触发
2.removeListener //从指定监听器数组中删除一个监听器,需要注意的是,此操作将会改变处于被删监听器之后的那些监听器索引
7-5 实例

通过connection的连接事件来演示EventEmitter类的应用
创建main.js文件,代码如下:

var events = require('events');
var eventEmitter = new events.EventEmitter();

//监听器1
var listener1 = function listener1(){
   console.log('监听器 listener1 执行。');
}

//监听器2
var listener2 = function listener2(){
   console.log('监听器 listener2 执行。');
}

// 绑定 connection 事件,处理函数为 listener1 
eventEmitter.addListener('connection',listener1);

// 绑定 connection 事件,处理函数为 listener2
eventEmitter.on('connection',listener2);

var eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + '个监听器监听连接事件')

//触发 connection事件
eventEmitter.emit('connection')

// 移除监绑定的 listener1 函数
eventEmitter.removeListener('connection',listener1);
console.log("listener1 不再受监听。");


//触发 connection事件
eventEmitter.emit('connection')

eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + '个监听器监听连接事件')

console.log("程序执行完毕。");

7-6 error事件

EventEmitter定义了一个特殊的事件error,它包含了错误的语义,我们在遇到异常的时候,通常会触发error事件
当error被触发时,EventEmitter规定如果没有响应的监听器,Node.js会把他当做异常,退出程序并输出错误信息。
我们一般要为会触发error事件的对象设置监听器,别面遇到错误后整个程序崩溃,例如:

//error.js
var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');
第7章 Node.js EventEmitter_第1张图片
error
7-7 继承EventEmitter

大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
为什么要这样做呢?原因有两点:
首先,具有某个实体功能的对象实现事件符合语义, 事件的监听和发生应该是一个对象的方法。
其次 JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。

你可能感兴趣的:(第7章 Node.js EventEmitter)