UNPKG

svelte

Version:

Cybernetically enhanced web apps

128 lines (125 loc) 3.82 kB
import { noop, safe_not_equal, run_all, is_function } from '../internal'; /** * Creates a `Readable` store that allows reading by subscription. * @param value initial value * @param {StartStopNotifier}start start and stop notifications for subscriptions */ function readable(value, start) { return { subscribe: writable(value, start).subscribe, }; } /** * Create a `Writable` store that allows both updating and reading by subscription. * @param {*=}value initial value * @param {StartStopNotifier=}start start and stop notifications for subscriptions */ function writable(value, start = noop) { let stop; const subscribers = []; function set(new_value) { if (safe_not_equal(value, new_value)) { value = new_value; if (!stop) { return; // not ready } subscribers.forEach((s) => s[1]()); subscribers.forEach((s) => s[0](value)); } } function update(fn) { set(fn(value)); } function subscribe(run, invalidate = noop) { const subscriber = [run, invalidate]; subscribers.push(subscriber); if (subscribers.length === 1) { stop = start(set) || noop; } run(value); return () => { const index = subscribers.indexOf(subscriber); if (index !== -1) { subscribers.splice(index, 1); } if (subscribers.length === 0) { stop(); stop = null; } }; } return { set, update, subscribe }; } /** * Derived value store by synchronizing one or more readable stores and * applying an aggregation function over its input values. * @param {Stores} stores input stores * @param {function(Stores=, function(*)=):*}fn function callback that aggregates the values * @param {*=}initial_value when used asynchronously */ function derived(stores, fn, initial_value) { const single = !Array.isArray(stores); const stores_array = single ? [stores] : stores; const auto = fn.length < 2; const invalidators = []; const store = readable(initial_value, (set) => { let inited = false; const values = []; let pending = 0; let cleanup = noop; const sync = () => { if (pending) { return; } cleanup(); const result = fn(single ? values[0] : values, set); if (auto) { set(result); } else { cleanup = is_function(result) ? result : noop; } }; const unsubscribers = stores_array.map((store, i) => store.subscribe((value) => { values[i] = value; pending &= ~(1 << i); if (inited) { sync(); } }, () => { run_all(invalidators); pending |= (1 << i); })); inited = true; sync(); return function stop() { run_all(unsubscribers); cleanup(); }; }); return { subscribe(run, invalidate = noop) { invalidators.push(invalidate); const unsubscribe = store.subscribe(run, invalidate); return () => { const index = invalidators.indexOf(invalidate); if (index !== -1) { invalidators.splice(index, 1); } unsubscribe(); }; } }; } /** * Get the current value from a store by subscribing and immediately unsubscribing. * @param store readable */ function get(store) { let value; store.subscribe((_) => value = _)(); return value; } export { readable, writable, derived, get };