UNPKG

@cdellacqua/signals

Version:

A simple signal pattern implementation that enables reactive programming

119 lines (118 loc) 3.01 kB
function deriveSignal(signal$, transform) { const base$ = makeSignal(); const emitTransformed = (data) => { base$.emit(transform(data)); }; const handleUnsubscribe = () => { if (unsubscribeOriginal && base$.nOfSubscriptions() === 0) { unsubscribeOriginal(); unsubscribeOriginal = null; } }; let unsubscribeOriginal = null; return { nOfSubscriptions: base$.nOfSubscriptions, subscribe: (s) => { const unsubscribe = base$.subscribe(s); if (!unsubscribeOriginal) { unsubscribeOriginal = signal$.subscribe(emitTransformed); } return () => { unsubscribe(); handleUnsubscribe(); }; }, subscribeOnce: (s) => { const unsubscribe = base$.subscribeOnce((v) => { s(v); handleUnsubscribe(); }); if (!unsubscribeOriginal) { unsubscribeOriginal = signal$.subscribe(emitTransformed); } return () => { unsubscribe(); handleUnsubscribe(); }; } }; } function coalesceSignals(signals$) { const base$ = makeSignal(); const emit = (data) => { base$.emit(data); }; const handleUnsubscribe = () => { if (unsubscribeOriginals && base$.nOfSubscriptions() === 0) { unsubscribeOriginals.forEach((unsub) => unsub()); unsubscribeOriginals = null; } }; let unsubscribeOriginals = null; return { nOfSubscriptions: base$.nOfSubscriptions, subscribe: (s) => { const unsubscribe = base$.subscribe(s); if (!unsubscribeOriginals) { unsubscribeOriginals = signals$.map((signal$) => signal$.subscribe(emit)); } return () => { unsubscribe(); handleUnsubscribe(); }; }, subscribeOnce: (s) => { const unsubscribe = base$.subscribeOnce((v) => { s(v); handleUnsubscribe(); }); if (!unsubscribeOriginals) { unsubscribeOriginals = signals$.map((signal$) => signal$.subscribe(emit)); } return () => { unsubscribe(); handleUnsubscribe(); }; } }; } function makeSignal() { const subscribers = []; function emit(v) { if (subscribers.length === 0) { return; } for (const subscriber of subscribers.slice()) { subscriber(v); } } function unsubscribe(subscriber) { const index = subscribers.indexOf(subscriber); if (index !== -1) { subscribers.splice(index, 1); } } function subscribe(subscriber) { const index = subscribers.indexOf(subscriber); if (index === -1) { subscribers.push(subscriber); } return () => unsubscribe(subscriber); } function subscribeOnce(subscriber) { const unsubscribeWrapper = subscribe((v) => { unsubscribeWrapper(); subscriber(v); }); return unsubscribeWrapper; } return { emit, subscribe, subscribeOnce, nOfSubscriptions() { return subscribers.length; } }; } export { coalesceSignals, deriveSignal, makeSignal };