123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import { DEFAULT_EVENT_PRIORITY } from '../../constants/priority';
- import { AnyFunction } from '../../types';
- import { forOwn, push, slice, toArray } from '../../utils';
- /**
- * The interface for the EventBus instance.
- *
- * @since 3.0.0
- */
- export interface EventBusObject {
- on( events: string | string[], callback: EventBusCallback, key?: object, priority?: number ): void;
- off( events: string | string[], key?: object ): void;
- offBy( key: object ): void;
- emit( event: string, ...args: any[] ): void;
- destroy(): void;
- }
- /**
- * The interface for each event handler object.
- *
- * @since 3.0.0
- */
- export interface EventHandler {
- _event: string;
- _callback: AnyFunction;
- _namespace: string;
- _priority: number;
- _key?: object;
- }
- /**
- * The type for a callback function of the EventBus.
- *
- * @since 3.0.0
- */
- export type EventBusCallback = AnyFunction;
- /**
- * The constructor to provided a simple event system.
- *
- * @since 3.0.0
- *
- * @return An EventBus object.
- */
- export function EventBus(): EventBusObject {
- /**
- * The collection of registered handlers.
- */
- let handlers: Record<string, EventHandler[]> = {};
- /**
- * Registers an event handler.
- *
- * @param events - An event name or names separated by spaces. Use a dot(.) to add a namespace.
- * @param callback - A callback function to register.
- * @param key - Optional. An object for an identifier of the handler.
- * @param priority - Optional. A priority number for the order in which the callbacks are invoked.
- * Lower numbers correspond with earlier execution. The default value is 10.
- */
- function on(
- events: string | string[],
- callback: EventBusCallback,
- key?: object,
- priority = DEFAULT_EVENT_PRIORITY
- ): void {
- forEachEvent( events, ( event, namespace ) => {
- handlers[ event ] = handlers[ event ] || [];
- push( handlers[ event ], {
- _event : event,
- _callback : callback,
- _namespace: namespace,
- _priority : priority,
- _key : key,
- } ).sort( ( handler1, handler2 ) => handler1._priority - handler2._priority );
- } );
- }
- /**
- * Removes event handlers registered by `on()`.
- * If only the event name is provided, all handlers that associate with the event are removed.
- * If the event name and namespace are specified, handlers that associate with the event and namespace are removed.
- *
- * @param events - An event name or names separated by spaces. Use a dot(.) to add a namespace.
- * @param key - Optional. An object for an identifier of the handler.
- */
- function off( events: string | string[], key?: object ): void {
- forEachEvent( events, ( event, namespace ) => {
- const eventHandlers = handlers[ event ];
- handlers[ event ] = eventHandlers && eventHandlers.filter( handler => {
- return handler._key ? handler._key !== key : key || handler._namespace !== namespace;
- } );
- } );
- }
- /**
- * Removes all handlers locked by the specified key.
- *
- * @param key - A key.
- */
- function offBy( key: object ): void {
- forOwn( handlers, ( eventHandlers, event ) => {
- off( event, key );
- } );
- }
- /**
- * Triggers callback functions.
- * This accepts additional arguments and passes them to callbacks.
- *
- * @param event - An event name.
- */
- function emit( event: string ): void {
- ( handlers[ event ] || [] ).forEach( handler => {
- // eslint-disable-next-line prefer-rest-params, prefer-spread
- handler._callback.apply( handler, slice( arguments, 1 ) );
- } );
- }
- /**
- * Removes all handlers.
- */
- function destroy(): void {
- handlers = {};
- }
- /**
- * Parses provided events and iterates over them.
- *
- * @param events - An event or events.
- * @param iteratee - An iteratee function.
- */
- function forEachEvent( events: string | string[], iteratee: ( event: string, namespace: string ) => void ): void {
- toArray( events ).join( ' ' ).split( ' ' ).forEach( eventNS => {
- const fragments = eventNS.split( '.' );
- iteratee( fragments[ 0 ], fragments[ 1 ] );
- } );
- }
- return {
- on,
- off,
- offBy,
- emit,
- destroy,
- };
- }
|