Once Handling in EventEmitter

Once Handling in EventEmitter

Mar 18, 2025 · 1 min read · 105 Words · -Views -Comments

EventEmitter Initial Version

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)
    }
}

Testing

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

When executing the above code, you’ll find that the test event was triggered once, but it should not execute because it was turned off. The solution is as follows.

Once Failure

...
 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)
    }

Final Thoughts

Read more source code

Alan H
Authors
Developer, Tech Enthusiast, Open Source Advocate