@lilbunnyrabbit/event-emitter
Version:
A lightweight and type-safe EventEmitter implementation for TypeScript.
176 lines • 5.76 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventEmitter = void 0;
/**
* Event emitter class capable of emitting and listening for typed events.
* It enables the creation of a strongly-typed, custom event handling system.
*
* @template TEvents - An object type mapping event names to their associated data types. Each key represents an event name, and its value represents the type of data associated with that event.
*
* @example
* ```ts
* type MyEvents = {
* data: string;
* loaded: void;
* error: Error;
* }
*
* const emitter = new EventEmitter<MyEvents>();
* ```
*/
class EventEmitter {
constructor() {
this.listeners = {};
this.globalListeners = new Set();
}
/**
* Adds an event listener for a specified event type.
* This method allows you to specify which event you are interested in listening to
* and to provide a callback function that will be executed whenever that event is emitted.
*
* @template TType - Event type.
* @param type - The identifier for the event type to listen for.
* @param listener - The callback function that will be called when the event is emitted.
* @returns The {@link EventEmitter} instance itself, allowing for method chaining.
*
* @example
* ```ts
* emitter.on("data", (data: string) => {
* console.log("Data", data);
* });
*
* emitter.on("loaded", function () {
* console.log(
* "Emitter loaded",
* this // EventEmitter<MyEvents>
* );
* });
*
* emitter.on("error", (error: Error) => {
* console.error(`Error: ${error.message}`);
* });
* ```
*/
on(type, listener) {
if (!(type in this.listeners)) {
this.listeners[type] = new Set();
}
this.listeners[type].add(listener);
return this;
}
/**
* Removes a previously registered event listener for a specified event type.
* Use this method to unregister listeners when they are no longer needed, preventing potential memory leaks.
*
* @template TType - Event type.
* @param type - The identifier for the event type from which to remove the listener.
* @param listener - The callback function to unregister.
* @return The {@link EventEmitter} instance itself, allowing for method chaining.
*
* @example
* ```ts
* const onError = (error: Error) => console.error(error);
*
* emitter.on("error", onError);
*
* // ...
*
* emitter.off("error", onError);
* ```
*/
off(type, listener) {
if (this.listeners[type] !== undefined) {
this.listeners[type].delete(listener);
}
return this;
}
/**
* Adds a global event listener that is called for every emitted event.
*
* @param listener - The global event listener to add.
* @returns The {@link EventEmitter} instance itself, allowing for method chaining.
*
* @example
* ```ts
* emitter.onAll((event: GlobalEvent<TEvents>) => {
* console.log(`Event of type ${String(event.type)} received`, event.data);
* });
* ```
*/
onAll(listener) {
this.globalListeners.add(listener);
return this;
}
/**
* Removes a previously registered global event listener.
*
* @param listener - The global event listener to remove.
* @returns The {@link EventEmitter} instance itself, allowing for method chaining.
*
* @example
* ```ts
* const globalListener = (event: GlobalEvent<TEvents>) => {
* console.log(`Event of type ${String(event.type)} received`, event.data);
* };
*
* emitter.onAll(globalListener);
*
* // ...
*
* emitter.offAll(globalListener);
* ```
*/
offAll(listener) {
this.globalListeners.delete(listener);
return this;
}
/**
* Emits an event of a specific type, invoking all registered listeners for that event type with the provided data.
* Also calls any global event listeners with a {@link GlobalEvent} object.
*
* @template TType - Event type.
* @param type - The identifier for the event type to emit.
* @param data - The data to pass to the event listeners. The type of this data is defined by the corresponding value in TEvents.
* @return The {@link EventEmitter} instance itself, allowing for method chaining.
*
* @example
* ```ts
* emitter.emit("data", "Sample data");
* emitter.emit("loaded");
* emitter.emit("error", new Error("Oh no!"));
* ```
*/
emit(type, ...data) {
var _a;
(_a = this.listeners[type]) === null || _a === void 0 ? void 0 : _a.forEach((listener) => listener.apply(this, data));
const globalEvent = {
type,
data: data.length ? data[0] : undefined,
};
for (const listener of this.globalListeners) {
listener.call(this, globalEvent);
}
return this;
}
/**
* Removes all listeners for all event types, as well as all global listeners.
*
* @returns The {@link EventEmitter} instance itself, allowing for method chaining.
*
* @example
* ```ts
* emitter.clear(); // No more event listeners remain
* ```
*/
clear() {
for (const key in this.listeners) {
if (Object.prototype.hasOwnProperty.call(this.listeners, key)) {
delete this.listeners[key];
}
}
this.globalListeners.clear();
return this;
}
}
exports.EventEmitter = EventEmitter;
//# sourceMappingURL=event-emitter.js.map