Event Source/Handler helpers DOM like
A few simple generic classes to create event sources and handlers with the same feel like the DOM events.
type eventMap<T> = { [key in keyof T]?: { handle: string, callback: (params: T[key]) => any }[] }
type BaseEvents = {
}
class EventProvider<T = BaseEvents> {
private eventMap: eventMap<T> = {}
private _id: string = this.generateHandle()
public get id(): string {
return this._id
}
private generateHandle(): string {
return `${new Date().getTime()}${Math.floor(Math.random() * 1000)}`
}
public invokeEvent<K extends keyof T>(event: K, params: T[K]): void {
this.eventMap[event]?.forEach(c => { c.callback(params) })
}
public addEventListener<K extends keyof T>(event: K, callback: (params: T[K]) => any): string {
if (!Object.keys(this.eventMap).includes(event as string))
this.eventMap[event] = []
const entry = { handle: this.generateHandle(), callback }
this.eventMap[event]!.push(entry)
return entry.handle
}
public removeEventListener(handle: string) {
Object.getOwnPropertyNames(this.eventMap).forEach((eventNames: any) => {
this.eventMap[eventNames as keyof T] = this.eventMap[eventNames as keyof T]!.filter(c => c.handle != handle)
})
}
}
Usage Example:
type TestClass1Events = {
"loaded": { var: string }
"unloaded": { var: number, var2: string }
}
class TestClass1 extends EventProvider<TestClass1Events> {
private test() {
this.invokeEvent("loaded", { var: "test" })
this.invokeEvent("unloaded", { var: 1, var2: "test" })
}
}
type TestClass2Events = TestClass1Events & {
"loadedV2": { var: string, max: number }
"unloadedV2": { var: number, max: string }
}
class TestClass2 extends EventProvider<TestClass2Events> {
private test() {
this.invokeEvent("loadedV2", { var: "test", max: 1 })
this.invokeEvent("unloadedV2", { var: 1, max: "test" })
}
}