UNPKG

seitu

Version:
70 lines (69 loc) • 1.67 kB
//#region src/core/subscription/index.ts function createReadableSubscription(get, subscribe, notify, getServer) { return { get, ...getServer ? { getServer } : {}, subscribe(callback, options) { return subscribe(() => callback(get()), options); }, "~": { output: null, notify } }; } /** * Subscribe/notify primitive used by every reactive handle. * * - `onFirstSubscribe` attaches on first subscriber and cleans up on last. * - `notify` calls every subscriber; the first throw is rethrown after the loop. * - `size` is the subscriber count. * * @example * ```ts twoslash * import { createSubscription } from 'seitu' * * const { subscribe, notify, size } = createSubscription({ * onFirstSubscribe: () => { * const id = setInterval(notify, 1000) * return () => clearInterval(id) * }, * }) * ``` */ function createSubscription(options) { const subscribers = /* @__PURE__ */ new Set(); let onEmpty; const notify = () => { let error; for (const cb of [...subscribers]) { if (!subscribers.has(cb)) continue; try { cb(); } catch (caught) { error ??= { caught }; } } if (error) throw error.caught; }; return { subscribe(callback, opts) { if (subscribers.size === 0 && options?.onFirstSubscribe) onEmpty = options.onFirstSubscribe() ?? void 0; subscribers.add(callback); if (opts?.immediate) callback(); return () => { if (!subscribers.delete(callback)) return; if (subscribers.size === 0) { onEmpty?.(); onEmpty = void 0; } }; }, notify, get size() { return subscribers.size; } }; } //#endregion export { createReadableSubscription, createSubscription };