UNPKG

3.99 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var internal = require('../internal');
6
7/**
8 * Creates a `Readable` store that allows reading by subscription.
9 * @param value initial value
10 * @param {StartStopNotifier}start start and stop notifications for subscriptions
11 */
12function readable(value, start) {
13 return {
14 subscribe: writable(value, start).subscribe,
15 };
16}
17/**
18 * Create a `Writable` store that allows both updating and reading by subscription.
19 * @param {*=}value initial value
20 * @param {StartStopNotifier=}start start and stop notifications for subscriptions
21 */
22function writable(value, start = internal.noop) {
23 let stop;
24 const subscribers = [];
25 function set(new_value) {
26 if (internal.safe_not_equal(value, new_value)) {
27 value = new_value;
28 if (!stop) {
29 return; // not ready
30 }
31 subscribers.forEach((s) => s[1]());
32 subscribers.forEach((s) => s[0](value));
33 }
34 }
35 function update(fn) {
36 set(fn(value));
37 }
38 function subscribe(run, invalidate = internal.noop) {
39 const subscriber = [run, invalidate];
40 subscribers.push(subscriber);
41 if (subscribers.length === 1) {
42 stop = start(set) || internal.noop;
43 }
44 run(value);
45 return () => {
46 const index = subscribers.indexOf(subscriber);
47 if (index !== -1) {
48 subscribers.splice(index, 1);
49 }
50 if (subscribers.length === 0) {
51 stop();
52 }
53 };
54 }
55 return { set, update, subscribe };
56}
57/**
58 * Derived value store by synchronizing one or more readable stores and
59 * applying an aggregation function over its input values.
60 * @param {Stores} stores input stores
61 * @param {function(Stores=, function(*)=):*}fn function callback that aggregates the values
62 * @param {*=}initial_value when used asynchronously
63 */
64function derived(stores, fn, initial_value) {
65 const single = !Array.isArray(stores);
66 const stores_array = single
67 ? [stores]
68 : stores;
69 const auto = fn.length < 2;
70 const invalidators = [];
71 const store = readable(initial_value, (set) => {
72 let inited = false;
73 const values = [];
74 let pending = 0;
75 let cleanup = internal.noop;
76 const sync = () => {
77 if (pending) {
78 return;
79 }
80 cleanup();
81 const result = fn(single ? values[0] : values, set);
82 if (auto) {
83 set(result);
84 }
85 else {
86 cleanup = internal.is_function(result) ? result : internal.noop;
87 }
88 };
89 const unsubscribers = stores_array.map((store, i) => store.subscribe((value) => {
90 values[i] = value;
91 pending &= ~(1 << i);
92 if (inited) {
93 sync();
94 }
95 }, () => {
96 internal.run_all(invalidators);
97 pending |= (1 << i);
98 }));
99 inited = true;
100 sync();
101 return function stop() {
102 internal.run_all(unsubscribers);
103 cleanup();
104 };
105 });
106 return {
107 subscribe(run, invalidate = internal.noop) {
108 invalidators.push(invalidate);
109 const unsubscribe = store.subscribe(run, invalidate);
110 return () => {
111 const index = invalidators.indexOf(invalidate);
112 if (index !== -1) {
113 invalidators.splice(index, 1);
114 }
115 unsubscribe();
116 };
117 }
118 };
119}
120/**
121 * Get the current value from a store by subscribing and immediately unsubscribing.
122 * @param store readable
123 */
124function get(store) {
125 let value;
126 store.subscribe((_) => value = _)();
127 return value;
128}
129
130exports.readable = readable;
131exports.writable = writable;
132exports.derived = derived;
133exports.get = get;