core/src/util/events.ts

126 lines
3.0 KiB
TypeScript

import { logger } from '../core';
/**
* Event emitter that can be scoped by plugin name or core.
*/
export class ScopedEventEmitter {
protected listeners: {[key: string]: any[]};
/**
* Add an event listener on `name` scope for event `event`. Alias of `on`.
* @param name Event scope
* @param event Event name
* @param func Listener
* @param once Listen once
* @see on
*/
public addEventListener = this.on;
constructor() {
this.listeners = {};
}
/**
* Add an event listener on `name` scope for event `event`.
* @param name Event scope
* @param event Event name
* @param func Listener
* @param once Listen once
*/
public on(name: string, event: string, func: any, once = false): void {
if (!func || !event || !name) {
throw new Error('missing arguments');
}
if (!this.listeners[name]) {
this.listeners[name] = [];
}
this.listeners[name].push({
event, func, name, once,
});
}
/**
* Add an one-off event listener on `name` scope for event `event`.
* @param name Event scope
* @param event Event name
* @param func Listener
*/
public once(name: string, event: string, func: any): void {
this.on(name, event, func, true);
}
/**
* Emit an event `event` to all listeners in all scopes.
* @param event Event name
* @param args Data
*/
public emit(event: string, ...args: any[]): void {
for (const name in this.listeners) {
for (const i in this.listeners[name]) {
if (!this.listeners[name]) {
break;
}
const listener = this.listeners[name][i];
if (listener.event === event && listener.func) {
try {
listener.func(...args);
} catch (e: any) {
logger.error('An error occured in one of the listeners for "%s":',
event, e.stack);
}
if (listener.once) {
this.listeners[name].splice(parseInt(i, 10), 1);
}
}
}
}
}
/**
* Emit an event `event` to listeners listening for scope `name`.
* @param name Scope name
* @param event Event name
* @param args Data
*/
public emitTo(name: string, event: string, ...args: any[]): void {
if (!this.listeners[name]) {
return;
}
for (const i in this.listeners[name]) {
if (!this.listeners[name]) {
break;
}
const listener = this.listeners[name][i];
if (listener.event === event && listener.func) {
try {
listener.func(...args);
} catch (e: any) {
logger.error('An error occured in one of the listeners for "%s", stream "%s":',
event, name, e.stack);
}
if (listener.once) {
this.listeners[name].splice(parseInt(i, 10), 1);
}
}
}
}
/**
* Remove all listeners for scope `name`.
* @param name Scope name
*/
public removeName(name: string): void {
if (this.listeners[name]) {
delete this.listeners[name];
}
}
}