simple-event-target
Version:
Thinnest possible wrapper around native events. It simplifies typing the custom event detail
42 lines (41 loc) • 1.47 kB
JavaScript
const eventType = 'batik';
/**
* Thinnest possible wrapper around native events
*
* @usage
* const smokeSignals = new SimpleEventTarget();
* smokeSignals.subscribe(details => console.log(details))
* smokeSignals.emit('The BBQ is ready');
*/
export default class SimpleEventTarget {
/**
* @deprecated Only for advanced use cases. Using this will break the type safety.
*/
get raw() {
return { eventType, eventTarget: this.#target };
}
#target = new EventTarget();
#weakListeners = new WeakMap();
subscribe(callback, options) {
this.#target.addEventListener(eventType, this.#getNativeListener(callback), options);
}
unsubscribe(callback) {
this.#target.removeEventListener(eventType, this.#getNativeListener(callback));
}
emit(detail) {
this.#target.dispatchEvent(new CustomEvent(eventType, { detail }));
}
// Permanently map simplified callbacks to native listeners.
// This acts as a memoization/deduplication which matches the native behavior.
// Calling `subscribe(cb); subscribe(cb); unsubscribe(cb)` should only add it once and remove it once.
#getNativeListener(callback) {
if (this.#weakListeners.has(callback)) {
return this.#weakListeners.get(callback);
}
const native = ((event) => {
callback(event.detail);
});
this.#weakListeners.set(callback, native);
return native;
}
}