retrobus
Version:
An event bus that allows listeners to be retroactive
103 lines (102 loc) • 3.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createEventBus = exports.clearEmittedEvents = exports.emit = exports.clearEventBusListeners = exports.removeEventBusListener = exports.addEventBusListener = void 0;
const CACHE_EMITTED_EVENT_LIMIT = 1000;
const emittedEvents = new Map();
const eventListeners = new Map();
const defaultOptions = {
retro: false,
retroStrategy: 'last-one',
once: false,
unique: false
};
const addEventBusListener = (name, callback, options = defaultOptions) => {
const unsubscribe = () => (0, exports.removeEventBusListener)(name, callback);
const listeners = eventListeners.get(name);
if (options.retro && emittedEvents.has(name)) {
const emittedEventArgs = emittedEvents.get(name);
switch (options.retroStrategy) {
case 'all': {
for (const args of emittedEventArgs) {
callback(...args);
}
break;
}
case 'last-one':
default: {
const args = emittedEventArgs[emittedEventArgs.length - 1];
callback(...args);
break;
}
}
if (options.once) {
return unsubscribe;
}
}
const listener = Object.assign({ callback }, options);
if (!listeners) {
eventListeners.set(name, [listener]);
return unsubscribe;
}
if (options.unique && listeners.find((c) => c.callback === callback)) {
return unsubscribe;
}
eventListeners.set(name, listeners.concat([listener]));
return unsubscribe;
};
exports.addEventBusListener = addEventBusListener;
const removeEventBusListener = (name, callback) => {
const calls = eventListeners.get(name);
if (!calls) {
return;
}
eventListeners.set(name, calls.filter((call) => call.callback !== callback));
};
exports.removeEventBusListener = removeEventBusListener;
const clearEventBusListeners = (name) => {
if (name === undefined) {
eventListeners.clear();
return;
}
eventListeners.delete(name);
};
exports.clearEventBusListeners = clearEventBusListeners;
const getLimitedHistoryOfEmittedEventArgs = (emittedEventArgs) => {
if (emittedEventArgs.length > CACHE_EMITTED_EVENT_LIMIT) {
return [...emittedEventArgs.slice(-CACHE_EMITTED_EVENT_LIMIT)];
}
return emittedEventArgs;
};
const emit = (name, ...args) => {
const listeners = eventListeners.get(name);
if (emittedEvents.has(name)) {
const emittedEventArgs = emittedEvents.get(name);
emittedEvents.set(name, getLimitedHistoryOfEmittedEventArgs(emittedEventArgs.concat([args])));
}
else {
emittedEvents.set(name, [args]);
}
if (!listeners) {
return;
}
listeners.map((call) => call.callback(...args));
eventListeners.set(name, listeners.filter((call) => !call.once));
};
exports.emit = emit;
const clearEmittedEvents = (name) => {
if (name === undefined) {
emittedEvents.clear();
return;
}
emittedEvents.delete(name);
};
exports.clearEmittedEvents = clearEmittedEvents;
const createEventBus = (event = Symbol()) => {
return {
emit: (payload) => (0, exports.emit)(event, payload),
clearEmittedEvents: () => (0, exports.clearEmittedEvents)(event),
addEventBusListener: (callback, options) => (0, exports.addEventBusListener)(event, callback, options),
clearEventBusListeners: () => (0, exports.clearEventBusListeners)(event)
};
};
exports.createEventBus = createEventBus;