# EventEmitter类
所有的 I/O 操作在完成时会发送一个事件到事件队列
Node.js 中很多对象都会分发事件,1. net.server 在每次有新链接时触发一个事件 2. fs.readStream 在文件被打开的时候触发一个事件
EventEmitter 核心是事件触发和事件监听器功能的封装
添加一个新的监听器时,newListener 被触发,当移除一个监听器时,removeListener 被触发
var { EventEmitter } = require('events')
var eventEmitter = new EventEmitter()
eventEmitter.on('some_event', function() {
onsole.log('some_event 事件触发');
})
setTimeout(() => {
eventEmitter.emit('some_event')
}, 2000)
执行这段代码,控制台在1s之后打印“some_event 事件触发”
原理:eventEmitter注册了一个事件监听器,通过setTimeout在1s之后向eventEmitter对象发送了some_event事件,此时会调用some_event监听器
EventEmitter 由一个事件名(字符串)和若干个事件参数组成,每个事件,支持若干个事件监听器
当事件触发时,注册到事件的监听器依次被调用,事件参数作为回调函数的参数传递
# 参数和this 传给监听器
当调用 普通的监听器函数 时,this 指向引用监听器绑定到的 EventEmitter 实例
ES6 箭头函数,this 不再是引用 EventEmitter 的实例
var { EventEmitter } = require('events')
var eventEmitter = new EventEmitter()
eventEmitter.on('some_event', function() {
onsole.log('some_event 事件触发', this );
// this 为 EventEmitter {
// _events:
// [Object: null prototype] {
// undefined: [Function],
// connection: [Function: connectHandler],
// data_received: [Function] },
// _eventsCount: 3,
// _maxListeners: undefined }}
})
setTimeout(() => {
eventEmitter.emit('some_event')
}, 2000)
var { EventEmitter } = require('events')
var eventEmitter = new EventEmitter()
eventEmitter.on('some_event', (a, b) => {
console.log(a, b, this)
// a1 b1 {}
})
eventEmitter.emit('some_event', 'a1', 'b1')
var event = new EventEmitter()
event.on('some_event', function(arg1, arg2) {
console.log('listener1----', arg1, arg2)
})
event.on('some_event', function(arg1, arg2, arg3) {
console.log('listener2----', arg1, arg2, arg3)
})
event.emit('some_event', '参数1', '参数2', { name: '参数3'})
# 异步 VS 同步
EventEmitter 按照注册顺序一次调用监听器。可以通过 setImmediate 和 process.nextTick 进行异步操作
process.nextTick 在本阶段立即执行
setImmediate 安排回调在 轮询 阶段完成后执行
var event = new EventEmiiter()
eventEmitter.on('some_event', function(a, b) {
setImmediate(() => {
console.log('异步执行:', a, b)
})
})
eventEmitter.emit('some_event', 1, 2)
eventEmitter.on('some_event1', function(a, b) {
process.nextTick(() => {
console.log('异步执行:', a, b)
})
})
eventEmitter.emit('some_event1', 3, 4)
console.log('异步执行完毕')
//
// 异步执行完毕
// 3 4
// 1 2
# 方法
属性 | 描述 |
---|---|
addListener(event, listener) | 为指定事件添加一个监听器到监听器数组的尾部 |
on(event, listener) | 指定事件注册一个监听器,接受一个字符串 event 和一个回调函数 |
emit(event, [arg1], [arg2], [...]) | 按监听器的顺序执行执行每个监听器,如果事件有注册监听返回 true,否则返回 false |
once(event, listener) | 为指定事件注册监听器,此监听器只触发一次,触发之后会立即移除 |
removeListener(event, listener) | 移除指定事件的指定监听器,该监听器必须是在事件中被注册过。接受两个参数,第一个是事件名称,第二个是回调函数名称 |
removeAllListeners([event]) | 移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器 |
setMaxListeners(n) | 默认情况下, EventEmitters 如果你添加的监听器超过 10 个就会输出警告信息。 setMaxListeners 函数用于改变监听器的默认限制的数量。 |
listeners(event) | 返回指定事件的监听器数组。 |
# 类方法
方法 | 描述 |
---|---|
listenerCount(emitter, event) | 返回指定事件的监听器数量 |
# 事件
方法 | 描述 |
---|---|
newListener(emitter, event) | 该事件在添加新监听器时被触发 |
removeListener(emitter, event) | 从指定监听器数组中删除一个监听器。需要注意的是,此操作将会改变处于被删监听器之后的那些监听器的索引。 |
# error 事件
程序遇到异常时,触发 error 事件
当 error 事件被触发时,EventEmitter 如果没有处理响应的异常监听器,则会退出程序,抛出异常信息
一般会为触发 error 事件设置监听器,避免遇到错误时,整个程序崩溃
eventEmitter.emit('error');
# 继承 EventEmitter
- fs net http 都是基于 EventEmitter 的子类 不会直接使用 EventEmitter
- 原因1: 具有某个实体功能对象实现事件符合语义,事件的监听和发生应该是一个对象的方法
- 原因2: javascript 对象是基于原型的,可支持继承,继承 EventEmitter 避免打乱原有的继承关系