Event Emitter
Medium
Solution
/* eslint-disable @typescript-eslint/no-explicit-any */
type Callback = (...args: any[]) => any;
type Subscription = {
unsubscribe: () => void;
};
export class EventEmitter {
private readonly events: Map<string, Set<Callback>>;
constructor() {
this.events = new Map();
}
private addEvent(eventName: string, callback: Callback): void {
const callbacks = this.events.get(eventName);
if (callbacks === undefined) {
this.events.set(eventName, new Set([callback]));
return;
}
callbacks.add(callback);
}
private removeEvent(eventName: string, callback: Callback): void {
const callbacks = this.events.get(eventName);
if (callbacks === undefined) {
return;
}
callbacks.delete(callback);
}
subscribe(eventName: string, callback: Callback): Subscription {
this.addEvent(eventName, callback);
return {
unsubscribe: () => {
this.removeEvent(eventName, callback);
},
};
}
emit(eventName: string, args: any[] = []): any {
const callbacks = this.events.get(eventName);
if (!callbacks) {
return [];
}
const results: any[] = [];
callbacks.forEach((callback) => results.push(callback(...args)));
return results;
}
}