Skip to content

Faster EventEmitter #63

@supahero1

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