44 lines
1.2 KiB
TypeScript
44 lines
1.2 KiB
TypeScript
import type { EventMap } from '../data/types';
|
|
|
|
type Handler<K extends keyof EventMap> = (payload: EventMap[K]) => void;
|
|
|
|
// Typed pub/sub. Handlers added/removed during an emit don't affect that emit
|
|
// (we snapshot the handler list), matching what scenes need on shutdown.
|
|
export class EventBus {
|
|
private handlers = new Map<keyof EventMap, Set<Handler<never>>>();
|
|
|
|
on<K extends keyof EventMap>(event: K, fn: Handler<K>): () => void {
|
|
let set = this.handlers.get(event);
|
|
if (!set) {
|
|
set = new Set();
|
|
this.handlers.set(event, set);
|
|
}
|
|
set.add(fn as Handler<never>);
|
|
return () => this.off(event, fn);
|
|
}
|
|
|
|
once<K extends keyof EventMap>(event: K, fn: Handler<K>): () => void {
|
|
const off = this.on(event, (payload) => {
|
|
off();
|
|
fn(payload);
|
|
});
|
|
return off;
|
|
}
|
|
|
|
off<K extends keyof EventMap>(event: K, fn: Handler<K>): void {
|
|
this.handlers.get(event)?.delete(fn as Handler<never>);
|
|
}
|
|
|
|
emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void {
|
|
const set = this.handlers.get(event);
|
|
if (!set) return;
|
|
for (const fn of [...set]) {
|
|
if (set.has(fn)) (fn as Handler<K>)(payload);
|
|
}
|
|
}
|
|
|
|
removeAll(): void {
|
|
this.handlers.clear();
|
|
}
|
|
}
|