Skip to content

Faster EventEmitter #63

Description

@supahero1

So needless to say, EventTarget is pretty damn slow. I wrote an identical interface to yours in event_emitter.ts:

export class ObjectEventEmitter {
    #events: Object<string, EventCallback[]> = {};
    /**
     *
     * @param {string} eventName The name of the event
     * @param  {...any} args The arguments that will be passed to the listener
     */
    protected emit(eventName: string, ...args: EventCallback[]): void {
        const listeners = this.#events[eventName];
        if(listeners === undefined) return;
        for(const callback in listeners) {
            callback(...args);
        }
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    #set(eventName: string, listener: EventCallback): void {
        const listeners = this.#events[eventName];
        if(listeners === undefined) {
            this.#events[eventName] = [listener];
        } else {
            listeners.push(listener);
        }
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    on(eventName: string, listener: EventCallback): void {
        this.#set(eventName, listener);
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    once(eventName: string, listener: EventCallback): void {
        this.#set(eventName, function() {
            listener();
            this.off(eventName, listener);
        }.bind(this));
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    off(eventName: string, listener: EventCallback): void {
        const listeners = this.#events[eventName];
        if(listeners == undefined) return;
        const length = listeners.length;
        for(let i = 0; i < length; ++i) {
            if(listeners[i] === listener) {
                listeners.splice(i, 1);
                return;
            }
        }
    }
}

Except line 2 doesn't work lol, and I don't know how to fix that.

Here are some benchs:

image
image

For the second bench with offing listeners, I also shuffled the initial array of functions that were added to the emitter classes, so deleting wouldn't be just straightforward popping the head of the array everytime.

I also compared Map() with a simple object, object being faster by about 27%.

Let me know of any issues with this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions