EventEmitter中的once处理

· 1 min read

EventEmitter初版

class EventEmitter{

    constructor(){
        this.events={}
    }

    on(type,listener){
       if(!this.events[type]){
        this.events[type]=[]
       }
       this.events[type].push(listener)
    }


    emit(type,...args){
        this.events[type].forEach(listener=>{
            listener.call(this,...args)
        })
    }

    off(type,listener){
        if(this.events[type]){
            const index=this.events[type].indexOf(listener)
            if(index!==-1){
                this.events[type].splice(index,1)
            }
        }
    }


    once(type,listener){
        const onceListener=(...args)=>{
            listener.call(this,...args)
            this.off(type,onceListener)
        }
        this.on(type,onceListener)
    }
}

测试

const eventEmitter=new EventEmitter()
const listener=(args)=>{
    console.log(args);
}
eventEmitter.once('test',listener)
eventEmitter.off('test',listener)
eventEmitter.emit('test',{a:1})

执行上述代码,会发现test事件被触发了一次,预期应该是不执行的,因为off了。解决办法如下。

once失效

...
 off(type,listener){
        if(this.events[type]){
            const index=this.events[type].findIndex(l=>l.fn===listener||l===listener)
            if(index!==-1){
                this.events[type].splice(index,1)
            }
        }
    }

... 

 once(type,listener){
        const onceListener=(...args)=>{
            listener.call(this,...args)
            this.off(type,onceListener)
        }
        onceListener.fn=listener
        this.on(type,onceListener)
    }

写在最后

多看源码