ray-lab/packages/renderer-webgl/source/kernel/EventEmitter.ts

105 lines
2.9 KiB
TypeScript

/**
* Allowed event name.
*/
type EventName = string | number | symbol;
type EventHandler<Value> = (value?: Value) => any;
/**
* An internally used event emitter model.
*/
class EventEmitter<EventMap extends Record<EventName, any> = {}> {
private eventMap = new Map<keyof EventMap, Set<Function>>;
/**
* Add a listener for a given event.
* @param event - event name.
* @param handler - event handler.
*/
public addListener<T extends keyof EventMap>(event: T, handler: EventHandler<EventMap[T]>): void {
let handlerSet = this.eventMap.get(event);
if (!handlerSet) {
handlerSet = new Set();
this.eventMap.set(event, handlerSet);
}
handlerSet.add(handler);
}
/**
* Alias of `EventEmitter.addListener`.
*/
public declare on: <T extends keyof EventMap>(event: T, handler: EventHandler<EventMap[T]>) => void;
/**
* Remove the listeners of a given event.
* @param event - event name.
* @param handler - event handler.
*/
public removeListener<T extends keyof EventMap>(event: T, handler: EventHandler<EventMap[T]>) {
let handlerSet = this.eventMap.get(event);
if (handlerSet) {
handlerSet.delete(handler);
}
}
/**
* Alias of `EventEmitter.removeListener`.
*/
public declare off: <T extends keyof EventMap>(event: T, handler: EventHandler<EventMap[T]>) => void;
/**
* Remove all listeners of a given event.
* @param event - event name.
* @param handler - event handler.
*/
public removeAllListener<T extends keyof EventMap>(event: T) {
this.eventMap.set(event, new Set());
}
/**
* Alias of `EventEmitter.removeAllListener`.
*/
public declare offAll: <T extends keyof EventMap>(event: T) => void;
/**
* emit event.
*/
public emit<T extends keyof EventMap>(...param: EventMap[T] extends void ? [T] : [T, EventMap[T]]) {
let handlerSet = this.eventMap.get(param[0]);
if (handlerSet) {
for (const handler of handlerSet) {
handler(param[1]);
}
}
}
/**
* Remove all listeners.
*/
public clearAllListener() {
this.eventMap.clear();
this.eventMap = new Map();
}
/**
* Get the number of listeners for a given event.
* @param event - event name.
*/
public listenerCount<T extends keyof EventMap>(event: T): number {
let handlerSet = this.eventMap.get(event);
if (handlerSet) {
return handlerSet.size;
}
else {
return 0;
}
}
}
// Register alias.
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.offAll = EventEmitter.prototype.removeAllListener;
export { EventEmitter };