@chocolatemilkdev/emitter
Version:
a basic event emitter.
177 lines (176 loc) • 7.38 kB
JavaScript
import { DefaultEmitterOptions } from "./Types/EmitterOptions.mjs";
import validateCallback from "./Utils/validateCallback.mjs";
import validateEventName from "./Utils/validateEventName.mjs";
export default class ChocolateMilkEmitter {
constructor(emitterOptions) {
this.listeners = new Map();
this.emitteds = new Map();
this.warned = false;
this.emitterOptions = ChocolateMilkEmitter.applyOptions(emitterOptions);
}
on(eventName, callback) {
var _a;
validateEventName(eventName);
validateCallback(callback);
callback.listenerData = {
once: false,
suspended: false
};
this.listeners.has(eventName) ? (_a = this.listeners.get(eventName)) === null || _a === void 0 ? void 0 : _a.push(callback) : this.listeners.set(eventName, [callback]);
let events = this.listeners.get(eventName);
if ((events.length > this.emitterOptions.limits.listenerLimit) && this.emitterOptions.limits.warn && !this.warned) {
this.warned = true;
process.emitWarning(`listener limit is ${this.emitterOptions.limits.listenerLimit}, but this events listener size is bigger than listener limit, but you can change this in emitterOptions`);
}
return this;
}
once(eventName, callback) {
var _a;
validateEventName(eventName);
validateCallback(callback);
callback.listenerData = {
once: true,
suspended: false
};
this.listeners.has(eventName) ? (_a = this.listeners.get(eventName)) === null || _a === void 0 ? void 0 : _a.push(callback) : this.listeners.set(eventName, [callback]);
let events = this.listeners.get(eventName);
if ((events.length > this.emitterOptions.limits.listenerLimit) && this.emitterOptions.limits.warn && !this.warned) {
this.warned = true;
process.emitWarning(`listener limit is ${this.emitterOptions.limits.listenerLimit}, but this events listener size is bigger than listener limit, but you can change this in emitterOptions`);
}
return this;
}
onceAsync(eventName) {
let promise = new Promise((resolve, reject) => {
//@ts-ignore
this.once(eventName, (...parameters) => {
try {
resolve(parameters);
}
catch (e) {
reject(e);
}
});
});
return promise;
}
off(eventName, callback) {
validateEventName(eventName);
validateCallback(callback);
if (!callback && this.listeners.has(eventName))
this.listeners.set(eventName, []);
if (callback && this.listeners.has(eventName))
this.listeners.set(eventName, this.listeners.get(eventName).filter((v) => v !== callback));
return this;
}
emit(eventName, ...parameters) {
validateEventName(eventName);
if (this.listeners.has(eventName) && this.listeners.get(eventName).length > 0) {
let events = this.listeners.get(eventName);
for (const callback of events) {
if (callback.listenerData.suspended)
return;
if (callback.listenerData.once)
this.off(eventName, callback);
let callbackRes = callback(...parameters);
if (callbackRes instanceof Promise)
callbackRes.then((v) => callback.listenerData["listened"] = true);
if (!this.emitteds.has(eventName))
this.emitteds.set(eventName, true);
else
callback.listenerData["listened"] = true;
return callbackRes;
}
}
}
hasListener(eventName, callback) {
validateEventName(eventName);
validateCallback(callback);
if (!this.listeners.has(eventName))
return false;
let events = this.listeners.get(eventName);
if (!callback)
return this.listeners.has(eventName);
else
return events.some((listener) => String(listener) === String(callback));
}
isListened(eventName) {
validateEventName(eventName);
if (!this.listeners.has(eventName))
return false;
let events = this.listeners.get(eventName);
return events.some((listener) => listener.listenerData.listened);
}
isEmitted(eventName) {
validateEventName(eventName);
if (!this.listeners.has(eventName))
return false;
return this.emitteds.has(eventName);
}
suspendListener(eventName, callback) {
validateEventName(eventName);
if (callback && typeof callback !== 'function')
throw new TypeError('\'callback\' is not function.');
let events = this.listeners.get(eventName);
if (!callback) {
for (const listener of events) {
listener.listenerData.suspended = true;
}
}
else {
let listener = events.find((v) => String(v) === String(callback));
listener.listenerData.suspended = true;
}
return void 0;
}
unsuspendListener(eventName, callback) {
validateEventName(eventName);
if (callback && typeof callback !== 'function')
throw new TypeError('\'callback\' is not function.');
let events = this.listeners.get(eventName);
if (!callback) {
for (const listener of events) {
listener.listenerData.suspended = false;
}
}
else {
let listener = events.find((v) => String(v) === String(callback));
listener.listenerData.suspended = false;
}
return void 0;
}
isSuspended(eventName, callback) {
validateEventName(eventName);
if (callback && typeof callback !== 'function')
throw new TypeError('\'callback\' is not function.');
let events = this.listeners.get(eventName);
if (!callback)
events.some((v) => v.listenerData.suspended);
else
return events.find((v) => String(v) === String(callback)).listenerData.suspended;
}
modifyListenerData(eventName, callback, listenerData) {
validateEventName(eventName);
validateCallback(callback);
let listener = this.listeners.get(eventName).find((v) => String(v) === String(callback));
listener.listenerData = listenerData;
this.listeners.set(eventName, this.listeners.get(eventName).filter((v) => v !== callback));
return this;
}
static applyOptions(emitterOptions) {
if (!emitterOptions)
emitterOptions = DefaultEmitterOptions;
if (!(emitterOptions === null || emitterOptions === void 0 ? void 0 : emitterOptions.limits))
emitterOptions.limits = {
listenerLimit: 8,
warn: true
};
if (emitterOptions.limits.warn === undefined)
emitterOptions.limits.warn = true;
if (!emitterOptions.limits.listenerLimit)
emitterOptions.limits.listenerLimit = 8;
if (!emitterOptions)
emitterOptions = DefaultEmitterOptions;
return emitterOptions;
}
}