You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
1.7 KiB
65 lines
1.7 KiB
// type FireKey = string
|
|
type FireFN = (...argu: any[]) => void
|
|
|
|
class FireEvent<T extends Record<string | symbol, FireFN>> {
|
|
#events: Record<keyof T, FireFN[]> = {} as any
|
|
print() {
|
|
Object.keys(this.#events).forEach(key => {
|
|
console.log(`${key}: ${this.#events[key]}\n`)
|
|
})
|
|
}
|
|
on<S extends keyof T | "*">(name: S, fn: S extends "*" ? (...argus: [keyof T, T[keyof T]]) => void : T[S]) {
|
|
if (!this.#events[name]) {
|
|
this.#events[name] = []
|
|
}
|
|
this.#events[name].push(fn as any)
|
|
}
|
|
async emit<S extends keyof T>(name: S, ...argu: Parameters<T[S]>) {
|
|
if (this.#events[name]) {
|
|
const returnValues: any = []
|
|
for (let i = 0; i < this.#events[name].length; i++) {
|
|
const fn = this.#events[name][i]
|
|
let r
|
|
if (Object.prototype.toString.call(fn) === "[object AsyncFunction]") {
|
|
r = await fn(...argu)
|
|
} else {
|
|
r = fn(...argu)
|
|
}
|
|
returnValues.push(r)
|
|
}
|
|
}
|
|
if (this.#events["*"]) {
|
|
for (let i = 0; i < this.#events["*"].length; i++) {
|
|
const fn = this.#events["*"][i]
|
|
fn(name, ...argu)
|
|
}
|
|
}
|
|
}
|
|
off<S extends keyof T>(name: S, fn?: T[S]) {
|
|
const len = this.#events[name].length
|
|
if (!len) {
|
|
return
|
|
}
|
|
if (!fn) {
|
|
this.#events[name] = []
|
|
} else {
|
|
for (let i = len - 1; i >= 0; i--) {
|
|
const _fn = this.#events[name][i]
|
|
if (_fn === fn) {
|
|
this.#events[name].splice(i, 1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
once<S extends keyof T>(name: S, fn: T[S]) {
|
|
const _fn: any = (...argu: any[]) => {
|
|
fn(...argu)
|
|
this.off<S>(name, _fn)
|
|
}
|
|
this.on(name, _fn)
|
|
}
|
|
}
|
|
|
|
export function buildEmitter<T extends Record<string | symbol, FireFN>>() {
|
|
return new FireEvent<T>()
|
|
}
|
|
|