Inital commit
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { pushUnique, removeItem } from "./collection";
|
||||
|
||||
export type EventMap<T> = Record<keyof T, any[]> | never;
|
||||
export type DefaultEventMap = [never];
|
||||
export type AnyRest = [...args: any[]];
|
||||
export type Args<K, T> = T extends DefaultEventMap ? AnyRest : K extends keyof T ? T[K] : never;
|
||||
export type Key<K, T> = T extends DefaultEventMap ? number : K | keyof T;
|
||||
export type Listener<K, T, F> = T extends DefaultEventMap
|
||||
? F
|
||||
: K extends keyof T
|
||||
? T[K] extends unknown[]
|
||||
? (...args: T[K]) => void
|
||||
: never
|
||||
: never;
|
||||
export type Listener1<K, T> = Listener<K, T, (...args: any[]) => void>;
|
||||
|
||||
export class BasicEventEmitter<T extends EventMap<T>> {
|
||||
private listeners = new Map<Key<any, Listener1<any, any>>, any>();
|
||||
|
||||
on<K>(eventName: Key<K, T>, listener: Listener1<K, T>): () => void {
|
||||
const arr = this.listeners.get(eventName) || [];
|
||||
pushUnique(arr, listener);
|
||||
this.listeners.set(eventName, arr);
|
||||
return () => {
|
||||
this.off(eventName, listener);
|
||||
};
|
||||
}
|
||||
|
||||
off<K>(eventName: Key<K, T>, listener: Listener1<K, T>): boolean {
|
||||
const arr = this.listeners.get(eventName) || [];
|
||||
removeItem(arr, listener);
|
||||
if (!arr.length) {
|
||||
this.listeners.delete(eventName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
emit<K>(eventName: Key<K, T>, ...args: Args<K, T>): Promise<unknown> {
|
||||
const listeners = this.listeners.get(eventName);
|
||||
const promises: Promise<unknown>[] = [];
|
||||
if (listeners) {
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
try {
|
||||
const listener = listeners[i];
|
||||
if (listener) {
|
||||
const result = listener(...args);
|
||||
if (result instanceof Promise) {
|
||||
promises.push(result);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
listenersCount<K>(type: Key<K, T>) {
|
||||
const arr = this.listeners.get(type);
|
||||
return arr ? arr.length : 0;
|
||||
}
|
||||
|
||||
removeAllListeners() {
|
||||
this.listeners.clear();
|
||||
}
|
||||
|
||||
removeSpecificListeners<K>(type: Key<K, T>) {
|
||||
this.listeners.delete(type);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user