Search code examples
javascripteventemitter

How to improve EventEmitter event notification function?


I wrote the following EventEmitter class, and it works great so far. But today I came across a scenario where if event listeners are created and destroyed frequently, and the off function is not used to remove the listener, there will be potential performance issues. How can I optimize this problem? Can anyone give me some ideas?

class EventEmitter {

    private listeners: Record<string, [Set<Function>, Set<Function>]> = {};

    existsEvent(eventName: string | number) {
        return !!this.listeners[eventName];
    }

    on(eventName: string | number, listener: Function) {
        if (!this.listeners[eventName]) {
            this.listeners[eventName] = [new Set(), new Set()];
        }
        this.listeners[eventName][0].add(listener);
    }

    once(eventName: string | number, listener: Function) {
        if (!this.listeners[eventName]) {
            this.listeners[eventName] = [new Set(), new Set()];
        }
        this.listeners[eventName][1].add(listener);
    }

    emit(eventName: string | number, ...args: any[]) {
        if (!this.listeners[eventName]) {
            return
        }

        this.listeners[eventName][0].forEach((listener: Function) => {
            listener(...args);
        });
        
        this.listeners[eventName][1].forEach((listener: Function) => {
            listener(...args);
        });
        this.listeners[eventName][1].clear();
    }

    off(eventName: string | number, listener: Function) {
        if (!this.listeners[eventName]) {
            return;
        }
        if (typeof listener === 'function') {
            this.listeners[eventName][0].delete(listener);
            this.listeners[eventName][1].delete(listener);
        } else {
            this.listeners[eventName][0].clear();
            this.listeners[eventName][1].clear();
        }
    }
}

export const eventEmitter = new EventEmitter();

Solution

  • To make good realization of Event Emitter like module need to have great knowledge of js architecture. That`s why most of cases developers use EE developed by big companies.

    To learn how they implemented need to look for few examples like default Node JS Event Emitter:

    https://github.com/nodejs/node/blob/main/lib/events.js

    or used long time ago by Meta (Facebook) its own version of EE for other goals than included in node (now archived), but as example still good:

    https://github.com/facebookarchive/emitter

    This examples will help to understand main concepts which each EE must have.

    But today I came across a scenario where if event listeners are created and destroyed frequently, and the off function is not used to remove the listener, there will be potential performance issues.

    You need to use off like methods or subscribe listeners via once methods.