130 lines
3.7 KiB
TypeScript
130 lines
3.7 KiB
TypeScript
// type EventCallback = (...args: any[]) => void;
|
|
|
|
// export class myEventEmitter {
|
|
// private events: Map<string, Set<EventCallback>>;
|
|
|
|
// constructor() {
|
|
// this.events = new Map();
|
|
// }
|
|
|
|
// public on(eventName: string, callback: EventCallback) {
|
|
// if (!this.events.has(eventName)) {
|
|
// this.events.set(eventName, new Set());
|
|
// }
|
|
|
|
// const eventListeners = this.events.get(eventName);
|
|
// eventListeners.add(callback);
|
|
// }
|
|
|
|
// public once(eventName: string, callback: EventCallback) {
|
|
// const onceCallback: EventCallback = (...args: any[]) => {
|
|
// this.off(eventName, onceCallback);
|
|
// callback(...args);
|
|
// };
|
|
// this.on(eventName, onceCallback);
|
|
// }
|
|
|
|
// public off(eventName: string, callback: EventCallback) {
|
|
// if (!this.events.has(eventName)) {
|
|
// return;
|
|
// }
|
|
|
|
// const eventListeners = this.events.get(eventName);
|
|
// let isSucc = eventListeners.delete(callback);
|
|
|
|
// if (eventListeners.size === 0) {
|
|
// this.events.delete(eventName);
|
|
// }
|
|
// }
|
|
|
|
// public emit(eventName: string, ...args: any[]) {
|
|
// if (!this.events.has(eventName)) {
|
|
// return;
|
|
// }
|
|
|
|
// const eventListeners = this.events.get(eventName);
|
|
// eventListeners.forEach((callback) => {
|
|
// callback(...args);
|
|
// });
|
|
// }
|
|
// }
|
|
|
|
|
|
type Listener<T extends any[]> = (...args: T) => void;
|
|
|
|
interface EventMap {
|
|
[event: string]: unknown[];
|
|
}
|
|
|
|
interface ListenerMap {
|
|
[event: string]: Listener<any>[];
|
|
}
|
|
|
|
interface EventEmitter {
|
|
on<T extends any[]>(event: string, listener: Listener<T>): this;
|
|
once<T extends any[]>(event: string, listener: Listener<T>): this;
|
|
off<T extends any[]>(event: string, listener: Listener<T>): this;
|
|
emit<T extends any[]>(event: string, ...args: T): this;
|
|
}
|
|
|
|
class EventEmitterImpl implements EventEmitter {
|
|
private events: EventMap = {};
|
|
private listeners: ListenerMap = {};
|
|
|
|
public on<T extends any[]>(event: string, listener: Listener<T>): this {
|
|
this.addListener(event, listener);
|
|
return this;
|
|
}
|
|
|
|
public once<T extends any[]>(event: string, listener: Listener<T>): this {
|
|
const onceListener: Listener<T> = (...args: T) => {
|
|
this.off(event, onceListener);
|
|
listener(...args);
|
|
};
|
|
this.addListener(event, onceListener);
|
|
return this;
|
|
}
|
|
|
|
public off<T extends any[]>(event: string, listener: Listener<T>): this {
|
|
const listeners = this.listeners[event];
|
|
if (!listeners) return this;
|
|
const index = listeners.indexOf(listener);
|
|
if (index >= 0) {
|
|
listeners.splice(index, 1);
|
|
if (listeners.length === 0) {
|
|
delete this.events[event];
|
|
delete this.listeners[event];
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public emit<T extends any[]>(event: string, ...args: T): this {
|
|
const listeners = this.listeners[event];
|
|
if (!listeners) return this;
|
|
const events = this.events[event] as T;
|
|
if (events) {
|
|
events.push(...args);
|
|
} else {
|
|
this.events[event] = args;
|
|
}
|
|
listeners.slice().forEach((listener) => listener(...args));
|
|
return this;
|
|
}
|
|
|
|
public clear(): void {
|
|
this.events = {};
|
|
this.listeners = {};
|
|
}
|
|
|
|
private addListener<T extends any[]>(event: string, listener: Listener<T>): void {
|
|
if (!this.listeners[event]) {
|
|
this.listeners[event] = [];
|
|
}
|
|
this.listeners[event].push(listener);
|
|
}
|
|
}
|
|
|
|
export const myEventEmitter = EventEmitterImpl;
|
|
|