Skip to main content
Module

x/event_emitter/mod.ts

Strictly typed Event Emitter for Deno.
Latest
File
interface EventListener<T> { once?: boolean callback: T[keyof T]}
/** Strictly typed Event Emitter for Deno. */class EventEmitter<T> { constructor (maxListeners?: number) { this.maxListeners = maxListeners ?? 5 }
private readonly maxListeners private readonly cache = new Map<keyof T, EventListener<T>[]>()
public on<Event extends keyof T> (event: Event, callback: T[Event]) { this.push(event, {callback}) }
public once<Event extends keyof T> (event: Event, callback: T[Event]) { this.push(event, {once: true, callback}) }
/** * Removes listener(s) from targeted event. * By default it gonna delete all listeners from particular event. You can delete specific listener by parsing it as second parameter. * It gonna return boolean value depending on result. */ public off<Event extends keyof T> (event: Event, callback?: T[Event]): boolean { if (!callback) return this.cache.delete(event)
let bucket = this.cache.get(event) if (!bucket) return false
const listenerCount = bucket.length bucket = bucket.filter(item => item.callback !== callback)
if (bucket.length === listenerCount) return false else { this.cache.set(event, bucket) return true } }
/** Synchronously calls each of the registered listeners (callbacks) in order. */ // deno-lint-ignore no-explicit-any public emit (event: keyof T, ...args: any) { let bucket = this.cache.get(event) if (!bucket) return
// deno-lint-ignore ban-types for (const item of bucket.values()) (item.callback as unknown as Function)(...args)
const listenerCount = bucket.length bucket = bucket.filter(item => !item.once)
if (listenerCount !== bucket.length) this.cache.set(event, bucket) }
private push (slot: keyof T, item: EventListener<T>) { const bucket = this.cache.get(slot) ?? [] if (this.maxListeners && this.maxListeners > 0 && bucket.length >= this.maxListeners) throw new TypeError(`EventEmitter: You cannot assign more than ${this.maxListeners} to "${slot}" event. You can increase this limit by setting custom max limit in constructor.`)
bucket.push(item) this.cache.set(slot, bucket) }
private toString () { return '[EventEmitter]' }
private toJSON () { return { events: [...this.cache.keys()], maxListeners: this.maxListeners } }}
export { EventEmitter }export type { EventListener }