@glandjs/events
Version:
A fast, zero‑dependency event broker and message bus for building scalable, event‑driven applications.
90 lines (89 loc) • 3.27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventEmitter = void 0;
const emitter_1 = require("@glandjs/emitter");
const event_watcher_1 = require("./event-watcher");
class EventEmitter {
constructor(separator, cacheSize, timeout = 1000, maxListeners = 5) {
this.defaultOptions = {
watch: false,
timeout: 1000,
defaultValue: null,
};
this.emitter = new emitter_1.EventEmitter(separator, cacheSize);
this.watcher = new event_watcher_1.EventWatcher(timeout);
this.maxListeners = maxListeners;
this.defaultOptions.timeout = timeout;
}
on(event, listener, options) {
const mergedOptions = { ...this.defaultOptions, ...options };
if (mergedOptions.watch) {
return this.watcher.watch(event, mergedOptions.timeout).then((result) => result, (error) => {
if (mergedOptions.defaultValue) {
return mergedOptions.defaultValue;
}
throw error;
});
}
if (!listener) {
throw new Error(`Listener cannot be null unless 'watch: true' is explicitly set in options.`);
}
const currentListeners = this.getListener(event);
if (currentListeners.length >= this.maxListeners) {
throw new Error(`Maximum listeners (${this.maxListeners}) exceeded for event '${event}'`);
}
this.emitter.on(event, listener);
return this;
}
watch(event, timeoutMs) {
return this.watcher.watch(event, timeoutMs || this.defaultOptions.timeout);
}
off(event, listener) {
this.emitter.off(event, listener);
return this;
}
emit(event, payload, options) {
this.watcher.onEmit(event, payload);
this.emitter.emit(event, payload);
if (options?.watch) {
this.watch(event, options.timeout).catch((err) => {
if (options.defaultValue) {
return options.defaultValue;
}
throw err;
});
}
}
shutdown() {
this.watcher.shutdown();
}
once(event, listener, options) {
const mergedOptions = { ...this.defaultOptions, ...options };
if (mergedOptions.watch) {
return this.watcher.watch(event, mergedOptions.timeout);
}
const currentListeners = this.getListener(event);
if (currentListeners.length >= this.maxListeners) {
throw new Error(`Maximum listeners (${this.maxListeners}) exceeded for event '${String(event)}'`);
}
const wrapper = (payload) => {
this.emitter.off(event, wrapper);
listener && listener(payload);
};
this.emitter.on(event, wrapper);
return this;
}
getListener(event) {
const parts = event.split(this.emitter['spliter']);
let node = this.emitter['tree'];
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (!node[part]) {
return [];
}
node = node[part];
}
return Array.isArray(node) ? node : [];
}
}
exports.EventEmitter = EventEmitter;