由于前不久做某厂的前端笔试题,遇到这道题没能实现出来,于是在此进行总结记录。
EventEmitter
是Node.js
中提供的一个监听器类,类似于前端vue
中的eventBus
事件总线。
其原理主要是发布订阅者模式。
用订阅杂志进行类比,所有的杂志就是一个大对象: events: {}
意林是其中一款杂志,那么意林就是events对象中的一个属性,值为数组(因为订阅意林杂志的人可以不止一个): events: {'意林': []}
当我订阅意林,那么我就应该收入倒意林数组中,让意林知道我订阅了它: events: {'意林': ['我']}
(这里’我’是执行函数)
最后,当意林发布了新一期杂志时,那么我就会收到这一期杂志,也就是意林对数组中的’我’进行了执行。
当我觉得意林不好看了,那我就会取消订阅,于是乎在意林数组中将我移除即可。
如果我只想看下一期的意林,下下一期的意林我不想看了,那么我就进行单次订阅即可。(使用once方法)
下面这个`EventEmitter`类进行了简单实现,主要实现 'on'、'emit'、'once'和'remove'四个方法
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| class EventEmitter { constructor() { this.events = {} }
on(eventName, callback) { if (!this.events[eventName]) { this.events[eventName] = [] } this.events[eventName].push(callback) return this }
emit(eventName, ...args) { if (!this.events[eventName]) { return this } const fns = this.events[eventName] fns.forEach(fn => fn.apply(this, args)) return this }
remove(eventName, callback) { if (!this.events[eventName]) { return this; } if (!callback) { this.events[eventName] = null return this } const index = this.events[eventName].indexOf(callback); this.events[eventName].splice(index, 1); return this; }
once(eventName, callback) { const only = () => { callback.apply(this, arguments); this.remove(eventName, only); }; this.on(eventName, only); return this; } }
const emt = new EventEmitter()
const listener1 = function (...args) { console.log('意林的第一个订阅者', ...args); }
const listener2 = function (...args) { console.log('意林的第二个订阅者', ...args); }
emt.on('yilin', listener1) emt.on('yilin', listener2)
setTimeout(() => { emt.remove('yilin', listener1) }, 500)
setTimeout(() => { emt.emit('yilin', 'hello world') }, 1000)
|
以上只是简单实现,如果有不正确的地方,还请各位大佬指正😀