Skip to content

Instantly share code, notes, and snippets.

@piotrgrundas
Last active November 14, 2023 12:29
Show Gist options
  • Save piotrgrundas/e7c2279dcb6c912b17d78b454ab9bedc to your computer and use it in GitHub Desktop.
Save piotrgrundas/e7c2279dcb6c912b17d78b454ab9bedc to your computer and use it in GitHub Desktop.
pub-sub EventEmitter
type EventCallback<Opts extends unknown = any> = Opts extends undefined
? (opts?: undefined) => void
: (opts: Opts) => void;
class EventEmitter<EventType = string> {
private listeners: Map<EventType, Array<EventCallback>>;
constructor() {
this.listeners = new Map();
this.addListeners = this.addListeners.bind(this);
this.emit = this.emit.bind(this);
}
addListeners(type: EventType, callback: EventCallback) {
const callbacks = this.listeners.get(type) ?? [];
const alreadyListening = callbacks.some((cb) => cb === callback);
if (!alreadyListening) {
callbacks.push(callback);
this.listeners.set(type, callbacks);
}
}
removeListeners(type: EventType, callback: EventCallback) {
const callbacks = this.listeners.get(type) ?? [];
const filteredCallbacks = callbacks.filter((cb) => cb !== callback);
if (callbacks.length !== filteredCallbacks.length) {
this.listeners.set(type, filteredCallbacks);
}
}
emit(type: EventType, opts?: unknown) {
const callbacks = this.listeners.get(type) ?? [];
callbacks.forEach((callback) => callback(opts));
}
}
export { type EventCallback };
export default EventEmitter;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment