首先第一步就是一个EventEmitter的类,然后考虑一下这个类的实例属性和实例方法。实例属性的话最基础的就是一个eventMap,可以是一个空对象,当然也可以这样创建Object.create(null)。如果需要还可以增加maxListener之类的属性。实例方法的话,最核心的就是adddeleteemit分别是添加事件,删除事件,发布事件。当然实际实现的时候,例如count,has,once(一次性添加),preAdd(添加在事件队列最前面),这些方法则是可以根据实际需求去添加。
以下代码均为简化的伪代码
EventEmitter.prototype.add=function(type,fn){if(!isFunction(fn))return;//判断是否在监听中添加的是合法的函数//判断type是否添加过,添加过一个还是多个函数if(this.event[type]){if(isArray(this.event[type])){//如果想要实现preadd将push改为unshift即可this.event[type].push(fn);}else{//如果想要实现preadd改变顺序this.event[type]=[this.event[type],fn];}}else{this.event[type]=fn;}}once方法参考一下node的once方法
functiononceWrapper(...args){if(!this.fired){this.target.removeListener(this.type,this.wrapFn);this.fired=true;Reflect.apply(this.listener,this.target,args);}}function_onceWrap(target,type,listener){varstate={fired:false,wrapFn:undefined,target,type,listener};varwrapped=onceWrapper.bind(state);wrapped.listener=listener;state.wrapFn=wrapped;returnwrapped;}EventEmitter.prototype.once=functiononce(type,listener){this.on(type,_onceWrap(this,type,listener));returnthis;};函数用onceWrap包裹,运行前需要对添加的监听进行移除
很简单理清楚几种边界情况就可以了
EventEmitter.prototype.delete=function(type,fn){//直接删除整类监听if(fn===undefined){this.events[type]&&deletethis.events[type];}else{//判断fn合法性就省了if(this.events[type]){if(this.events[type]===fn){deletethis.events[type];}else{for(variinthis.events[type]){if(this.events[type][i]===fn){if(i===0){this.events[type].shift();}else{this.events[type].splice(i,1);}}}if(this.events[type].length===1)this.events[type]=this.events[type][0];}}}}emitEventEmitter.prototype.emit=function(type){//获取参数varargs=[].slice.call(arguments,1);varhandler=events[type];if(handler===undefined)returnfalse;if(typeofhandler==='function'){handle.apply(this,args);}else{varlen=handler.length;constlisteners=arrayClone(handler,len);for(vari=0;i 这里提一下node的event的错误事件 如果有需要在自己的实践中也可以增加一个错误处理的机制,保证event实例的稳定性 一个事件订阅发布类其实不难实现,而在node中有很多厉害的类都是继承的事件类,而之后我会接着对node文件系统进行学习