@solid-primitives/event-bus
Version:
A collection of SolidJS primitives providing various features of a pubsub/event-emitter/event-bus.
81 lines (80 loc) • 2.89 kB
JavaScript
import { push } from "@solid-primitives/utils/immutable";
import {} from "@solid-primitives/utils";
import { batch, createEffect, createSignal, on } from "solid-js";
/**
* Turns a stream-like listen function, into a promise resolving when the first event is captured.
* @param subscribe listen function from any EventBus/Emitter
* @returns a promise resulting in the captured event value
*
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/event-bus#toPromise
*
* @example
* const emitter = createEventBus<string>();
* const event = await toPromise(emitter.listen);
*/
export function toPromise(subscribe) {
return new Promise(resolve => once(subscribe, resolve));
}
/**
* Listen to any EventBus/Emitter, but the listener will automatically unsubscribe on the first captured event. So the callback will run only **once**.
*
* @param subscribe Emitter's `listen` function
* @param listener callback called when an event is emitted
*
* @returns unsubscribe function
*
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/event-bus#once
*
* @example
* const { listen, emit } = createEventBus<string>();
* const unsub = once(listen, event => console.log(event));
*
* emit("foo") // will log "foo" and unsub
*
* emit("bar") // won't log
*/
export function once(subscribe, listener) {
const unsub = subscribe(payload => {
unsub();
listener(payload);
});
return unsub;
}
/**
* Wraps `emit` calls inside a `createEffect`. It causes that listeners execute having an reactive owner available. It allows for usage of effects, memos and other primitives inside listeners, without having to create a synthetic root.
*
* @param emit the emit function of any emitter/event-bus
* @returns modified emit function
*
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/event-bus#toEffect
*
* @example
* const { listen, emit } = createEventBus();
* const emitInEffect = toEffect(emit);
* listen(() => console.log(getOwner()))
*
* // ...sometime later (after root initiation):
* emit() // listener will log `null`
* emitInEffect() // listener will log an owner object
*/
export function toEffect(emit) {
const [stack, setStack] = createSignal([]);
createEffect(on(stack, stack => {
if (!stack.length)
return;
setStack([]);
stack.forEach(emit);
}));
return (payload) => void setStack(p => push(p, payload));
}
/**
* Wraps `emit` calls inside a `batch` call. It causes that listeners execute in a single batch, so they are not executed in sepatate queue ticks.
*
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/event-bus#batchEmits
*/
export function batchEmits(bus) {
return {
...bus,
emit: (...args) => batch(() => bus.emit(...args)),
};
}