一、是什么
我们了解到,Node
采用了事件驱动机制,而EventEmitter
就是Node
实现事件驱动的基础
在EventEmitter
的基础上,Node
几乎所有的模块都继承了这个类,这些模块拥有了自己的事件,可以绑定/触发监听器,实现了异步操作
Node.js
里面的许多对象都会分发事件,比如 fs.readStream 对象会在文件被打开的时候触发一个事件
这些产生事件的对象都是 events.EventEmitter 的实例,这些对象有一个 eventEmitter.on() 函数,用于将一个或多个函数绑定到命名事件上
二、使用方法
Node
的events
模块只提供了一个EventEmitter
类,这个类实现了Node
异步事件驱动架构的基本模式——观察者模式
在这种模式中,被观察者(主体)维护着一组其他对象派来(注册)的观察者,有新的对象对主体感兴趣就注册观察者,不感兴趣就取消订阅,主体有更新的话就依次通知观察者们
基本代码如下所示:
1 2 3 4 5 6 7 8 9 10 11
| const EventEmitter = require('events')
class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter()
function callback() { console.log('触发了event事件!') } myEmitter.on('event', callback) myEmitter.emit('event') myEmitter.removeListener('event', callback);
|
通过实例对象的on
方法注册一个名为event
的事件,通过emit
方法触发该事件,而removeListener
用于取消事件的监听
关于其常见的方法如下:
- emitter.addListener/on(eventName, listener) :添加类型为 eventName 的监听事件到事件数组尾部
- emitter.prependListener(eventName, listener):添加类型为 eventName 的监听事件到事件数组头部
- emitter.emit(eventName[, …args]):触发类型为 eventName 的监听事件
- emitter.removeListener/off(eventName, listener):移除类型为 eventName 的监听事件
- emitter.once(eventName, listener):添加类型为 eventName 的监听事件,以后只能执行一次并删除
- emitter.removeAllListeners([eventName]): 移除全部类型为 eventName 的监听事件
三、实现过程
通过上面的方法了解,EventEmitter
是一个构造函数,内部存在一个包含所有事件的对象
1 2 3 4 5
| class EventEmitter { constructor() { this.events = {}; } }
|
其中events
存放的监听事件的函数的结构如下:
1 2 3 4 5
| { "event1": [f1,f2,f3], "event2": [f4,f5], ... }
|
然后开始一步步实现实例方法,首先是emit
,第一个参数为事件的类型,第二个参数开始为触发事件函数的参数,实现如下:
1 2 3 4 5
| emit(type, ...args) { this.events[type].forEach((item) => { Reflect.apply(item, this, args); }); }
|
当实现了emit
方法之后,然后实现on
、addListener
、prependListener
这三个实例方法,都是添加事件监听触发函数,实现也是大同小异
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| on(type, handler) { if (!this.events[type]) { this.events[type] = []; } this.events[type].push(handler); }
addListener(type,handler){ this.on(type,handler) }
prependListener(type, handler) { if (!this.events[type]) { this.events[type] = []; } this.events[type].unshift(handler); }
|
紧接着就是实现事件监听的方法removeListener/on
1 2 3 4 5 6 7 8 9 10
| removeListener(type, handler) { if (!this.events[type]) { return; } this.events[type] = this.events[type].filter(item => item !== handler); }
off(type,handler){ this.removeListener(type,handler) }
|
最后再来实现once
方法, 再传入事件监听处理函数的时候进行封装,利用闭包的特性维护当前状态,通过fired
属性值判断事件函数是否执行过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| once(type, handler) { this.on(type, this._onceWrap(type, handler, this)); }
_onceWrap(type, handler, target) { const state = { fired: false, handler, type , target}; const wrapFn = this._onceWrapper.bind(state); state.wrapFn = wrapFn; return wrapFn; }
_onceWrapper(...args) { if (!this.fired) { this.fired = true; Reflect.apply(this.handler, this.target, args); this.target.off(this.type, this.wrapFn); } }
|
完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| class EventEmitter { constructor(){ this.events={}; } on(type,handler){ if(!this.events[type]){ this.events[type]=[] } this.events[type].push(handler) } addListener(type,handler){ this.on(type,handler)
} prependListener(type,handler){ if(!this.events[type]){ this.events[type]=[] } this.events[type].unshift(handler) } removeListener(type,handler){ if(!this.events[type]){ return; } this.events[type]=this.events[type].filter(item=>item!==handler) } off(type,handler){ this.removeListener(type,handler) } emit(type,...args){ this.events[type].forEach(item=>{ Reflect.apply(item,this,args); }) } once(type,handler){ let temp=(...args)=>{ handler(args); this.off(type,temp) } this.on(event,temp) } }
|