CustomEventEmitter
since: v1.0.0
The CustomEventEmitter class provides a mechanism to emit and listen to custom events in your application. It supports adding, removing, and dispatching events with options for one-time listeners, event preparation, and debugging. The class enforces rules for destructible and non dispatchable events using lock symbols, ensuring robust event management and error handling.
customEventEmitterErrorScope app error scope array
is exported by this utility and can be used to filter thrown
AppError
by scope for this specific utility.
Usage
import { CustomEventEmitter, type EventData } from '@mustib/utils';
type Events = { eventName: EventData<string>;};
new CustomEventEmitter<Events>({eventName: {}}).addListener('eventName', console.log) // 'value'.dispatch('eventName', 'value');Definition
export class CustomEventEmitter<EventMaps extends Record<string, DefaultEventData>> {}Generics
EventMaps- a record of event names and their corresponding event data
Constructor()
type CustomEventEmitter = new (events: { [name in keyof EventMaps]-?: ConstructorEventData<EventMaps[name]>; })- parameters
events- a record of event names and their corresponding event data
Properties
debugListeners
visibility : protected
Type : Set<EventDebugListener> | undefined
default : undefined
This property holds a set of all debug listeners added to the event emitter.
events
visibility : protected
type events = { [name: string | number | symbol]: { lockSymbol?: symbol; destructible: boolean; dispatchable: boolean; destructed: boolean;
prepare?<Event extends DefaultEventData>( value: Event['dispatchValue'], ): Event['listenerValue'];
listeners: { normal: Set<(value: any) => void>; prepend: Set<(value: any) => void>; all: Map<(value: any) => void, { isOnce: boolean; listener(value: any): void; priority: 'normal' | 'prepend'; } >; }; };}This property holds a record of all events added to the event emitter, with their corresponding details, where listeners are grouped by priority (normal and prepend) and stored in the normal and prepend sets, respectively. Additionally, all listeners are stored in the all map with their details, allowing for efficient lookups and removals.
Methods
addListener()
prependListener()
visibility : public
type addOrPrependListener = <Name extends keyof EventMaps>( name: Name, listener: (value: EventMaps[Name]['listenerValue']) => void, listenerOptions?: { once?: boolean; }) => this;This method adds or prepends a new listener to an event
Parameters
-
nametype name = keyof EventMaps;- The name of the event to add or prepend the listener to.
-
listenertype listener = (value: EventMaps[Name]['listenerValue']) => void;- The listener function to add or prepend.
- It will be called after the event is dispatched.
- Its `value` parameter is the `prepare` result (if defined), otherwise the dispatched value.
-
listenerOptionstype listenerOptions = { once?: boolean };once: a boolean indicating whether the listener should be removed after it is called once.
Returns
type T = this;removeListener()
visibility : public
type removeListener<Name extends keyof EventMaps> = ( name: Name, listener: (value: EventMaps[Name]['listenerValue']) => void,) => this;This method removes a listener from an event
Parameters
-
nametype name = keyof EventMaps;- The name of the event to remove the listener from.
-
listenertype listener = (value: EventMaps[Name]['listenerValue']) => void;- The listener function to remove.
Returns
type T = this;hasEvent()
visibility : protected
type hasEvent = (name: keyof EventMaps) => boolean;This method checks if an event exists
Parameters
-
nametype name = keyof EventMaps;- The name of the event to check.
Returns
type T = boolean;dispatch()
visibility : public
type dispatch = <Name extends keyof EventMaps>( name: Name, value: EventMaps[Name]['dispatchValue'], options?: { lockSymbol: symbol }) => void;This method dispatches an event
Parameters
-
nametype name = keyof EventMaps;- The name of the event to dispatch.
-
valuetype value = EventMaps[Name]['dispatchValue'];- Value passed to prepare if defined, otherwise to the listener.
-
optionstype options = { lockSymbol: symbol };- `lockSymbol`: a symbol used to unlock non-dispatchable events.
Returns
type T = this;destruct()
visibility : public
type destruct = <Name extends keyof EventMaps>( name: Name, lockSymbol: EventMaps[Name]['destructible'] extends true ? symbol : never,) => this;This method destructs an event
Parameters
-
nametype name = keyof EventMaps;- The name of the event to destruct.
-
lockSymboltype lockSymbol = symbol;- A symbol used to unlock destructible events.
Returns
type T = this;debug()
visibility : public
type DebugOperations = 'added listener' | 'prepended listener' | 'removed listener' | 'dispatched' | 'destructed';type EventDebugListener = (eventName: string, operationType: DebugOperations, details?: any) => void;type debug = (listener: EventDebugListener) => this;This method adds a debug listener to the event emitter.
Parameters
-
listenertype listener = EventDebugListener;- Function called for event operations.
- `eventName`: the name of the event.
- `operationType`: type of operation performed.
- `details`: additional details about the operation.
Returns
type T = this;insertListenerPriority()
visibility : protected
type insertListenerPriority = <Name extends keyof EventMaps>( options: { name: keyof EventMaps; listener: (value: any) => void; listenerOptions?: AddListenerOptions; priority: 'normal' | 'prepend'; }) => void;This method is used by the addListener and prependListener methods to insert a listener at a specific priority.
Parameters
-
optionstype options = { name: keyof EventMaps; listener: (value: any) => void; listenerOptions?: AddListenerOptions; priority: 'normal' | 'prepend' };- Same as add/prepend listener options, with explicit `priority`.
- Priority is `'normal'` for addListener and `'prepend'` for prependListener.
Returns
type T = void;Event Data
type EventData< ListenerValue = any, DispatchValue = ListenerValue, Dispatchable = true, Destructible = false,> = { listenerValue: ListenerValue; dispatchValue: DispatchValue; dispatchable: Dispatchable; destructible: Destructible;};A utility type that simplifies defining event data.
-
ListenerValue
- the type of the value passed to the event listener
-
DispatchValue
- the type of the value passed to the
dispatchmethod - it is defaulted to
ListenerValueso you don’t have to specify it if your event just passes the same value to the listener and thedispatchmethod.
- the type of the value passed to the
-
Dispatchable
- a boolean indicating whether the event can be dispatched
-
Destructible
- a boolean indicating whether the event can be destructed
ConstructorEventData
type ConstructorEventData = { [key in 'listener' | 'prepend']?: (value: Event['listenerValue']) => void | { options: ListenerOptions; listener: (value: Event['listenerValue']) => void }} & { prepare?: (value: Event['dispatchValue']) => Event['dispatchValue']; dispatchable?: boolean; destructible?: boolean; lockSymbol?: symbol; runningBehavior?: 'sync' | 'async' | 'async-sequential'} & { [key in 'beforeAll' | 'afterAll']: <Event extends DefaultEventData>(data: { dispatchValue: Event['dispatchValue']; listenerValue: Event['listenerValue']; listenerCount: number; }) => void | Promise<void>}-
listener and prepend
- a function that will be added as a listener or an object that contains a listener function and it’s options.
- it can be used to add or prepend a listener at initialization time.
- see add or prepend listener for more details
-
prepare
- a function that transforms the dispatched value before it is passed to the listener.
- it is required if the type of the dispatched value is different from the type of the value expected by the listener.
-
dispatchable
- a boolean indicating whether the event can be dispatched.
-
destructible
- a boolean indicating whether the event can be destructed.
-
lockSymbol
- a symbol that will be used to unlock the event.
- it is required if the event is destructible or non dispatchable.
-
runningBehavior
- since: v2.3.0
- a string with the value
sync,async, orasync-sequential. sync: the default behavior, all events are executed synchronously.async: all events are executed asynchronously but will not wait for async listeners to resolve.async-sequential: all events are executed asynchronously and will wait for for current listener to resolve before executing the next listener.
-
beforeAll and afterAll
- since: v2.3.0
- functions that will be called before and after all listeners are executed.
- they receive an object with the following properties:
dispatchValue: the value passed to thedispatchmethod see DispatchValue for more details.listenerValue: the value passed to the listener see ListenerValue for more details.listenerCount: the number of listeners that (will be or have been) executed.