easy-signal 3.2.2 → 3.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,7 +28,7 @@ export interface ReactiveSignal<T> extends ComputedSignal<T> {
28
28
  */
29
29
  export interface ComputedSignal<T> {
30
30
  (): T;
31
- subscribe: (subscriber: ReactiveSignalSubscriber<T>, timing?: Timing | null) => Unsubscribe;
31
+ subscribe: (subscriber: ReactiveSignalSubscriber<T>, when?: Timing | null, deferInitial?: boolean) => Unsubscribe;
32
32
  }
33
33
  /**
34
34
  * A Signal Subscriber is a function that will be called whenever the signal's value changes. The subscriber will be
@@ -76,7 +76,7 @@ export declare function reactiveSignal<T>(value: T, options?: SignalOptions<T>):
76
76
  *
77
77
  * The returned function can be called to unsubscribe from the Signal.
78
78
  */
79
- export declare function subscribe<T>(signal: ReactiveSignal<T>, subscriber: ReactiveSignalSubscriber<T>, timing?: Timing | null): Unsubscribe;
79
+ export declare function subscribe<T>(signal: ReactiveSignal<T>, changeHandler: ReactiveSignalSubscriber<T>, timing?: Timing | null, deferInitial?: boolean): Unsubscribe;
80
80
  /**
81
81
  * Get notified when a Signal's subscribers changes from none to some or some to none.
82
82
  */
@@ -91,7 +91,7 @@ export declare function onSubscriptionChange(signal: ReactiveSignal<any>, onChan
91
91
  * The optional second argument, `timing`, can be used to specify when the function should be called. The default is
92
92
  * undefined which executes the function immediately.
93
93
  */
94
- export declare function observe(fn: ReactiveSignalObserver, timing?: Timing): Unsubscribe;
94
+ export declare function observe(fn: ReactiveSignalObserver, timing?: Timing, deferInitial?: boolean): Unsubscribe;
95
95
  /**
96
96
  * Create a Computed Signal which is a signal that is the result of a function that depends on other signals. The
97
97
  * function is called immediately whenever the computed signal is accessed if there are no subscribers, or whenever its
@@ -101,4 +101,4 @@ export declare function observe(fn: ReactiveSignalObserver, timing?: Timing): Un
101
101
  * undefined which executes the function immediately after any change to any signal it relies on. This can
102
102
  * prevent unnecessary updates if the function is expensive to run.
103
103
  */
104
- export declare function computedSignal<T>(fn: ReactiveSignalUpdater<T>, when?: Timing): ComputedSignal<T>;
104
+ export declare function computedSignal<T>(fn: ReactiveSignalUpdater<T>, when?: Timing, deferInitial?: boolean): ComputedSignal<T>;
@@ -10,6 +10,7 @@ export const Timing = {
10
10
  },
11
11
  };
12
12
  let context = null;
13
+ let getHasSubscribers = false;
13
14
  // A map to keep track of listeners to subscription changes
14
15
  const onSubscriptionChanges = new WeakMap();
15
16
  /**
@@ -28,6 +29,8 @@ export function reactiveSignal(value, options) {
28
29
  const signal = ((newValue, set) => {
29
30
  // If no new value is provided, subscribe the current run to this signal and return the current value
30
31
  if (!set && newValue === undefined) {
32
+ if (getHasSubscribers)
33
+ return subscribers.size > 0;
31
34
  // If there is a context (an observer is running), add the observer's subscriber to the signal
32
35
  if (context) {
33
36
  const { subscriber: run, unsubscribes } = context;
@@ -84,20 +87,23 @@ export function reactiveSignal(value, options) {
84
87
  *
85
88
  * The returned function can be called to unsubscribe from the Signal.
86
89
  */
87
- export function subscribe(signal, subscriber, timing = Timing.Tick) {
90
+ export function subscribe(signal, changeHandler, timing = Timing.Tick, deferInitial = false) {
91
+ let subscriber;
88
92
  if (timing) {
89
93
  let queued = false;
90
- const subFn = subscriber;
91
94
  subscriber = () => {
92
95
  if (!queued) {
93
96
  queued = true;
94
97
  timing(() => {
95
98
  queued = false;
96
- subFn(signal());
99
+ changeHandler(signal());
97
100
  });
98
101
  }
99
102
  };
100
103
  }
104
+ else {
105
+ subscriber = changeHandler;
106
+ }
101
107
  // Set the current context so we can get the unsubscribe
102
108
  context = { prior: context, subscriber, unsubscribes: new Set() };
103
109
  // Get the current value of the signal
@@ -106,8 +112,8 @@ export function subscribe(signal, subscriber, timing = Timing.Tick) {
106
112
  const unsubscribe = context.unsubscribes.values().next().value;
107
113
  // Clear the current context
108
114
  context = context.prior;
109
- // Call the subscriber with the current value
110
- subscriber(value);
115
+ // Call the changeHandler with the current value immediately, regardless of timing, unless deferred
116
+ deferInitial ? subscriber(value) : changeHandler(value);
111
117
  // Return the unsubscribe function
112
118
  return unsubscribe;
113
119
  }
@@ -122,6 +128,11 @@ export function onSubscriptionChange(signal, onChange) {
122
128
  onSubscriptionChanges.set(signal, (onChanges = new Set()));
123
129
  // Add the onChange function to the set
124
130
  onChanges.add(onChange);
131
+ // Pretty little hack to get the current value of hasSubscribers
132
+ getHasSubscribers = true;
133
+ const hasSubscribers = signal();
134
+ getHasSubscribers = false;
135
+ onChange(hasSubscribers);
125
136
  // Return a function that removes the onChange function from the set
126
137
  return () => {
127
138
  onChanges.delete(onChange);
@@ -137,7 +148,7 @@ export function onSubscriptionChange(signal, onChange) {
137
148
  * The optional second argument, `timing`, can be used to specify when the function should be called. The default is
138
149
  * undefined which executes the function immediately.
139
150
  */
140
- export function observe(fn, timing) {
151
+ export function observe(fn, timing, deferInitial) {
141
152
  let dirty = true;
142
153
  let unsubscribes = new Set();
143
154
  // Subscribe to all the signals that are called when the effect is run
@@ -169,7 +180,7 @@ export function observe(fn, timing) {
169
180
  context = context.prior;
170
181
  };
171
182
  // Call immediately (or on the next timing)
172
- if (timing)
183
+ if (deferInitial && timing)
173
184
  timing(() => onChange());
174
185
  else
175
186
  onChange();
@@ -185,7 +196,7 @@ export function observe(fn, timing) {
185
196
  * undefined which executes the function immediately after any change to any signal it relies on. This can
186
197
  * prevent unnecessary updates if the function is expensive to run.
187
198
  */
188
- export function computedSignal(fn, when) {
199
+ export function computedSignal(fn, when, deferInitial) {
189
200
  // Create the signal
190
201
  const signal = reactiveSignal(undefined);
191
202
  // Store the unsubscribe function from the observer. We will only observe the function when there are subscribers to
@@ -196,7 +207,7 @@ export function computedSignal(fn, when) {
196
207
  // If there are subscribers, start observing the function
197
208
  if (hasSubscribers) {
198
209
  if (!unsubscribe)
199
- unsubscribe = observe(() => signal(fn), when);
210
+ unsubscribe = observe(() => signal(fn), when, deferInitial);
200
211
  }
201
212
  else if (unsubscribe) {
202
213
  // If there are no subscribers, stop observing the function
@@ -1 +1 @@
1
- {"version":3,"file":"reactiveSignal.js","sourceRoot":"","sources":["../src/reactiveSignal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reactiveSignal.js","sourceRoot":"","sources":["../src/reactiveSignal.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easy-signal",
3
- "version": "3.2.2",
3
+ "version": "3.2.4",
4
4
  "description": "A tiny (25 LOC), simple utility for alerting subscribers when an event happens, allowing for error handling and clearing.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -22,6 +22,7 @@ export const Timing = {
22
22
  // The context for the current run and its unsubscribes
23
23
  type Context = { prior: Context | null; subscriber: ReactiveSignalSubscriber<any>; unsubscribes: Set<Unsubscribe> };
24
24
  let context: Context | null = null;
25
+ let getHasSubscribers = false;
25
26
 
26
27
  // A map to keep track of listeners to subscription changes
27
28
  const onSubscriptionChanges = new WeakMap<ReactiveSignal<any>, Set<SubscriptionChange>>();
@@ -48,7 +49,7 @@ export interface ReactiveSignal<T> extends ComputedSignal<T> {
48
49
  */
49
50
  export interface ComputedSignal<T> {
50
51
  (): T;
51
- subscribe: (subscriber: ReactiveSignalSubscriber<T>, timing?: Timing | null) => Unsubscribe;
52
+ subscribe: (subscriber: ReactiveSignalSubscriber<T>, when?: Timing | null, deferInitial?: boolean) => Unsubscribe;
52
53
  }
53
54
 
54
55
  /**
@@ -101,6 +102,8 @@ export function reactiveSignal<T>(value: T, options?: SignalOptions<T>): Reactiv
101
102
  const signal = ((newValue?: T | ReactiveSignalUpdater<T>, set?: boolean) => {
102
103
  // If no new value is provided, subscribe the current run to this signal and return the current value
103
104
  if (!set && newValue === undefined) {
105
+ if (getHasSubscribers) return subscribers.size > 0;
106
+
104
107
  // If there is a context (an observer is running), add the observer's subscriber to the signal
105
108
  if (context) {
106
109
  const { subscriber: run, unsubscribes } = context;
@@ -169,21 +172,24 @@ export function reactiveSignal<T>(value: T, options?: SignalOptions<T>): Reactiv
169
172
  */
170
173
  export function subscribe<T>(
171
174
  signal: ReactiveSignal<T>,
172
- subscriber: ReactiveSignalSubscriber<T>,
173
- timing: Timing | null = Timing.Tick
175
+ changeHandler: ReactiveSignalSubscriber<T>,
176
+ timing: Timing | null = Timing.Tick,
177
+ deferInitial = false
174
178
  ): Unsubscribe {
179
+ let subscriber: ReactiveSignalSubscriber<T>;
175
180
  if (timing) {
176
181
  let queued = false;
177
- const subFn = subscriber;
178
182
  subscriber = () => {
179
183
  if (!queued) {
180
184
  queued = true;
181
185
  timing(() => {
182
186
  queued = false;
183
- subFn(signal());
187
+ changeHandler(signal());
184
188
  });
185
189
  }
186
190
  };
191
+ } else {
192
+ subscriber = changeHandler;
187
193
  }
188
194
 
189
195
  // Set the current context so we can get the unsubscribe
@@ -198,8 +204,8 @@ export function subscribe<T>(
198
204
  // Clear the current context
199
205
  context = context.prior;
200
206
 
201
- // Call the subscriber with the current value
202
- subscriber(value);
207
+ // Call the changeHandler with the current value immediately, regardless of timing, unless deferred
208
+ deferInitial ? subscriber(value) : changeHandler(value);
203
209
 
204
210
  // Return the unsubscribe function
205
211
  return unsubscribe;
@@ -213,7 +219,7 @@ export function onSubscriptionChange(
213
219
  onChange: (hasSubscribers: boolean) => void
214
220
  ): Unsubscribe {
215
221
  // Get the set of onChange functions for the signal
216
- let onChanges = onSubscriptionChanges.get(signal);
222
+ let onChanges = onSubscriptionChanges.get(signal)!;
217
223
 
218
224
  // If there is no set, create one and add it to the map
219
225
  if (!onChanges) onSubscriptionChanges.set(signal, (onChanges = new Set()));
@@ -221,9 +227,15 @@ export function onSubscriptionChange(
221
227
  // Add the onChange function to the set
222
228
  onChanges.add(onChange);
223
229
 
230
+ // Pretty little hack to get the current value of hasSubscribers
231
+ getHasSubscribers = true;
232
+ const hasSubscribers = signal();
233
+ getHasSubscribers = false;
234
+ onChange(hasSubscribers);
235
+
224
236
  // Return a function that removes the onChange function from the set
225
237
  return () => {
226
- onChanges!.delete(onChange);
238
+ onChanges.delete(onChange);
227
239
  };
228
240
  }
229
241
 
@@ -237,7 +249,7 @@ export function onSubscriptionChange(
237
249
  * The optional second argument, `timing`, can be used to specify when the function should be called. The default is
238
250
  * undefined which executes the function immediately.
239
251
  */
240
- export function observe(fn: ReactiveSignalObserver, timing?: Timing): Unsubscribe {
252
+ export function observe(fn: ReactiveSignalObserver, timing?: Timing, deferInitial?: boolean): Unsubscribe {
241
253
  let dirty = true;
242
254
  let unsubscribes = new Set<Unsubscribe>();
243
255
 
@@ -274,7 +286,7 @@ export function observe(fn: ReactiveSignalObserver, timing?: Timing): Unsubscrib
274
286
  };
275
287
 
276
288
  // Call immediately (or on the next timing)
277
- if (timing) timing(() => onChange());
289
+ if (deferInitial && timing) timing(() => onChange());
278
290
  else onChange();
279
291
 
280
292
  // Return a function that unsubscribes from all the signals that are called when the effect is run
@@ -290,7 +302,11 @@ export function observe(fn: ReactiveSignalObserver, timing?: Timing): Unsubscrib
290
302
  * undefined which executes the function immediately after any change to any signal it relies on. This can
291
303
  * prevent unnecessary updates if the function is expensive to run.
292
304
  */
293
- export function computedSignal<T>(fn: ReactiveSignalUpdater<T>, when?: Timing): ComputedSignal<T> {
305
+ export function computedSignal<T>(
306
+ fn: ReactiveSignalUpdater<T>,
307
+ when?: Timing,
308
+ deferInitial?: boolean
309
+ ): ComputedSignal<T> {
294
310
  // Create the signal
295
311
  const signal = reactiveSignal<T>(undefined as T);
296
312
 
@@ -302,7 +318,7 @@ export function computedSignal<T>(fn: ReactiveSignalUpdater<T>, when?: Timing):
302
318
  onSubscriptionChange(signal, hasSubscribers => {
303
319
  // If there are subscribers, start observing the function
304
320
  if (hasSubscribers) {
305
- if (!unsubscribe) unsubscribe = observe(() => signal(fn), when);
321
+ if (!unsubscribe) unsubscribe = observe(() => signal(fn), when, deferInitial);
306
322
  } else if (unsubscribe) {
307
323
  // If there are no subscribers, stop observing the function
308
324
  unsubscribe();