synstate 0.1.1 → 1.0.0
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.
- package/README.md +317 -298
- package/dist/core/class/child-observable-class.d.mts.map +1 -1
- package/dist/core/class/child-observable-class.mjs +43 -10
- package/dist/core/class/child-observable-class.mjs.map +1 -1
- package/dist/core/class/observable-base-class.d.mts +4 -4
- package/dist/core/class/observable-base-class.d.mts.map +1 -1
- package/dist/core/class/observable-base-class.mjs +8 -8
- package/dist/core/class/observable-base-class.mjs.map +1 -1
- package/dist/core/class/root-observable-class.d.mts +1 -1
- package/dist/core/class/root-observable-class.d.mts.map +1 -1
- package/dist/core/class/root-observable-class.mjs +9 -9
- package/dist/core/class/root-observable-class.mjs.map +1 -1
- package/dist/core/combine/combine.d.mts +7 -7
- package/dist/core/combine/combine.mjs +13 -14
- package/dist/core/combine/combine.mjs.map +1 -1
- package/dist/core/combine/merge.d.mts +6 -6
- package/dist/core/combine/merge.mjs +9 -9
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +20 -19
- package/dist/core/combine/zip.d.mts.map +1 -1
- package/dist/core/combine/zip.mjs +22 -21
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/{interval.d.mts → counter.d.mts} +14 -12
- package/dist/core/create/counter.d.mts.map +1 -0
- package/dist/core/create/{interval.mjs → counter.mjs} +21 -23
- package/dist/core/create/counter.mjs.map +1 -0
- package/dist/core/create/from-abortable-promise.d.mts +29 -0
- package/dist/core/create/from-abortable-promise.d.mts.map +1 -0
- package/dist/core/create/from-abortable-promise.mjs +70 -0
- package/dist/core/create/from-abortable-promise.mjs.map +1 -0
- package/dist/core/create/from-promise.d.mts +9 -6
- package/dist/core/create/from-promise.d.mts.map +1 -1
- package/dist/core/create/from-promise.mjs +8 -5
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.d.mts +4 -4
- package/dist/core/create/from-subscribable.mjs +4 -4
- package/dist/core/create/index.d.mts +3 -3
- package/dist/core/create/index.d.mts.map +1 -1
- package/dist/core/create/index.mjs +4 -4
- package/dist/core/create/just.d.mts +32 -0
- package/dist/core/create/just.d.mts.map +1 -0
- package/dist/core/create/just.mjs +44 -0
- package/dist/core/create/just.mjs.map +1 -0
- package/dist/core/create/source.d.mts +7 -12
- package/dist/core/create/source.d.mts.map +1 -1
- package/dist/core/create/source.mjs +1 -6
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.d.mts +6 -4
- package/dist/core/create/timer.d.mts.map +1 -1
- package/dist/core/create/timer.mjs +6 -7
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/index.d.mts +1 -1
- package/dist/core/index.d.mts.map +1 -1
- package/dist/core/index.mjs +21 -14
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/operators/audit.d.mts +97 -0
- package/dist/core/operators/audit.d.mts.map +1 -0
- package/dist/core/operators/audit.mjs +144 -0
- package/dist/core/operators/audit.mjs.map +1 -0
- package/dist/core/operators/debounce.d.mts +88 -0
- package/dist/core/operators/debounce.d.mts.map +1 -0
- package/dist/core/operators/debounce.mjs +130 -0
- package/dist/core/operators/debounce.mjs.map +1 -0
- package/dist/core/operators/filter.d.mts +5 -5
- package/dist/core/operators/filter.mjs +3 -3
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/index.d.mts +4 -4
- package/dist/core/operators/index.d.mts.map +1 -1
- package/dist/core/operators/index.mjs +6 -6
- package/dist/core/operators/map.d.mts +41 -0
- package/dist/core/operators/map.d.mts.map +1 -0
- package/dist/core/operators/map.mjs +71 -0
- package/dist/core/operators/map.mjs.map +1 -0
- package/dist/core/operators/merge-map.d.mts +57 -30
- package/dist/core/operators/merge-map.d.mts.map +1 -1
- package/dist/core/operators/merge-map.mjs +59 -32
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.d.mts +6 -6
- package/dist/core/operators/pairwise.mjs +9 -9
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.d.mts +6 -6
- package/dist/core/operators/scan.mjs +9 -9
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.d.mts +21 -9
- package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs +25 -13
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.d.mts +5 -5
- package/dist/core/operators/skip-until.mjs +8 -8
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.d.mts +18 -9
- package/dist/core/operators/skip-while.d.mts.map +1 -1
- package/dist/core/operators/skip-while.mjs +28 -16
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.d.mts +57 -26
- package/dist/core/operators/switch-map.d.mts.map +1 -1
- package/dist/core/operators/switch-map.mjs +59 -28
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.d.mts +5 -5
- package/dist/core/operators/take-until.mjs +8 -8
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.d.mts +15 -8
- package/dist/core/operators/take-while.d.mts.map +1 -1
- package/dist/core/operators/take-while.mjs +19 -13
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/throttle.d.mts +81 -0
- package/dist/core/operators/throttle.d.mts.map +1 -0
- package/dist/core/operators/throttle.mjs +126 -0
- package/dist/core/operators/throttle.mjs.map +1 -0
- package/dist/core/operators/with-buffered-from.d.mts +13 -9
- package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs +17 -13
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.d.mts +14 -9
- package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs +18 -13
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.d.mts +5 -5
- package/dist/core/operators/with-initial-value.mjs +8 -8
- package/dist/core/operators/with-initial-value.mjs.map +1 -1
- package/dist/core/predefined/index.d.mts +2 -0
- package/dist/core/predefined/index.d.mts.map +1 -0
- package/dist/core/predefined/index.mjs +12 -0
- package/dist/core/predefined/index.mjs.map +1 -0
- package/dist/core/predefined/operators/attach-index.d.mts +57 -0
- package/dist/core/predefined/operators/attach-index.d.mts.map +1 -0
- package/dist/core/predefined/operators/attach-index.mjs +62 -0
- package/dist/core/predefined/operators/attach-index.mjs.map +1 -0
- package/dist/core/predefined/operators/index.d.mts +12 -0
- package/dist/core/predefined/operators/index.d.mts.map +1 -0
- package/dist/core/predefined/operators/index.mjs +12 -0
- package/dist/core/predefined/operators/index.mjs.map +1 -0
- package/dist/core/predefined/operators/map-optional.d.mts +51 -0
- package/dist/core/predefined/operators/map-optional.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-optional.mjs +55 -0
- package/dist/core/predefined/operators/map-optional.mjs.map +1 -0
- package/dist/core/predefined/operators/map-result-err.d.mts +51 -0
- package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-result-err.mjs +55 -0
- package/dist/core/predefined/operators/map-result-err.mjs.map +1 -0
- package/dist/core/predefined/operators/map-result-ok.d.mts +51 -0
- package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-result-ok.mjs +55 -0
- package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -0
- package/dist/core/predefined/operators/map-to.d.mts +43 -0
- package/dist/core/predefined/operators/map-to.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-to.mjs +48 -0
- package/dist/core/predefined/operators/map-to.mjs.map +1 -0
- package/dist/core/predefined/operators/pluck.d.mts +47 -0
- package/dist/core/predefined/operators/pluck.d.mts.map +1 -0
- package/dist/core/predefined/operators/pluck.mjs +52 -0
- package/dist/core/predefined/operators/pluck.mjs.map +1 -0
- package/dist/core/predefined/operators/skip.d.mts +50 -0
- package/dist/core/predefined/operators/skip.d.mts.map +1 -0
- package/dist/core/predefined/operators/skip.mjs +56 -0
- package/dist/core/predefined/operators/skip.mjs.map +1 -0
- package/dist/core/predefined/operators/take.d.mts +44 -0
- package/dist/core/predefined/operators/take.d.mts.map +1 -0
- package/dist/core/predefined/operators/take.mjs +49 -0
- package/dist/core/predefined/operators/take.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-optional.d.mts +44 -0
- package/dist/core/predefined/operators/unwrap-optional.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-optional.mjs +50 -0
- package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-err.d.mts +44 -0
- package/dist/core/predefined/operators/unwrap-result-err.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-err.mjs +48 -0
- package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts +44 -0
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-ok.mjs +50 -0
- package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -0
- package/dist/core/types/id.d.mts +1 -1
- package/dist/core/types/id.d.mts.map +1 -1
- package/dist/core/types/index.d.mts +1 -0
- package/dist/core/types/index.d.mts.map +1 -1
- package/dist/core/types/observable-family.d.mts +8 -14
- package/dist/core/types/observable-family.d.mts.map +1 -1
- package/dist/core/types/observable.d.mts +3 -3
- package/dist/core/types/observable.d.mts.map +1 -1
- package/dist/core/types/timer.d.mts +2 -0
- package/dist/core/types/timer.d.mts.map +1 -0
- package/dist/core/types/timer.mjs +2 -0
- package/dist/core/types/timer.mjs.map +1 -0
- package/dist/core/utils/id-maker.d.mts +2 -2
- package/dist/core/utils/id-maker.d.mts.map +1 -1
- package/dist/core/utils/id-maker.mjs +3 -3
- package/dist/core/utils/id-maker.mjs.map +1 -1
- package/dist/core/utils/index.mjs +1 -1
- package/dist/entry-point.mjs +24 -15
- package/dist/entry-point.mjs.map +1 -1
- package/dist/globals.d.mts +0 -3
- package/dist/index.mjs +24 -15
- package/dist/index.mjs.map +1 -1
- package/dist/utils/collect-to-array.d.mts +3 -0
- package/dist/utils/collect-to-array.d.mts.map +1 -0
- package/dist/utils/collect-to-array.mjs +11 -0
- package/dist/utils/collect-to-array.mjs.map +1 -0
- package/dist/utils/create-boolean-state.d.mts +40 -0
- package/dist/utils/create-boolean-state.d.mts.map +1 -0
- package/dist/utils/create-boolean-state.mjs +53 -0
- package/dist/utils/create-boolean-state.mjs.map +1 -0
- package/dist/utils/create-event-emitter.d.mts +4 -4
- package/dist/utils/create-event-emitter.mjs +4 -4
- package/dist/utils/create-reducer.d.mts +10 -7
- package/dist/utils/create-reducer.d.mts.map +1 -1
- package/dist/utils/create-reducer.mjs +7 -7
- package/dist/utils/create-reducer.mjs.map +1 -1
- package/dist/utils/create-state.d.mts +8 -48
- package/dist/utils/create-state.d.mts.map +1 -1
- package/dist/utils/create-state.mjs +10 -60
- package/dist/utils/create-state.mjs.map +1 -1
- package/dist/utils/index.d.mts +2 -0
- package/dist/utils/index.d.mts.map +1 -1
- package/dist/utils/index.mjs +3 -1
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +17 -11
- package/src/core/class/child-observable-class.mts +65 -9
- package/src/core/class/circular-dependency-comparison.test.mts +142 -0
- package/src/core/class/circular-dependency.test.mts +251 -0
- package/src/core/class/observable-base-class.mts +9 -9
- package/src/core/class/root-observable-class.mts +14 -10
- package/src/core/combine/combine.mts +15 -15
- package/src/core/combine/merge.mts +13 -14
- package/src/core/combine/zip.mts +26 -25
- package/src/core/create/{interval.mts → counter.mts} +32 -30
- package/src/core/create/from-abortable-promise.mts +83 -0
- package/src/core/create/from-promise.mts +10 -7
- package/src/core/create/from-subscribable.mts +4 -4
- package/src/core/create/index.mts +3 -3
- package/src/core/create/just.mts +43 -0
- package/src/core/create/source.mts +10 -14
- package/src/core/create/timer.mts +12 -11
- package/src/core/index.mts +1 -1
- package/src/core/operators/audit.mts +172 -0
- package/src/core/operators/debounce.mts +154 -0
- package/src/core/operators/filter.mts +9 -9
- package/src/core/operators/index.mts +4 -4
- package/src/core/operators/map.mts +124 -0
- package/src/core/operators/merge-map.mts +60 -33
- package/src/core/operators/pairwise.mts +10 -10
- package/src/core/operators/scan.mts +10 -10
- package/src/core/operators/skip-if-no-change.mts +26 -14
- package/src/core/operators/skip-until.mts +9 -9
- package/src/core/operators/skip-while.mts +30 -28
- package/src/core/operators/switch-map.mts +60 -29
- package/src/core/operators/take-until.mts +9 -9
- package/src/core/operators/take-while.mts +21 -19
- package/src/core/operators/{throttle-time.mts → throttle.mts} +58 -38
- package/src/core/operators/with-buffered-from.mts +18 -14
- package/src/core/operators/with-current-value-from.mts +19 -14
- package/src/core/operators/with-initial-value.mts +9 -9
- package/src/core/predefined/index.mts +1 -0
- package/src/core/predefined/operators/attach-index.mts +62 -0
- package/src/core/predefined/operators/index.mts +11 -0
- package/src/core/predefined/operators/map-optional.mts +55 -0
- package/src/core/predefined/operators/map-result-err.mts +55 -0
- package/src/core/predefined/operators/map-result-ok.mts +55 -0
- package/src/core/predefined/operators/map-to.mts +45 -0
- package/src/core/predefined/operators/pluck.mts +51 -0
- package/src/core/predefined/operators/skip.mts +57 -0
- package/src/core/predefined/operators/take.mts +47 -0
- package/src/core/predefined/operators/unwrap-optional.mts +49 -0
- package/src/core/predefined/operators/unwrap-result-err.mts +48 -0
- package/src/core/predefined/operators/unwrap-result-ok.mts +49 -0
- package/src/core/types/id.mts +1 -1
- package/src/core/types/index.mts +1 -0
- package/src/core/types/observable-family.mts +8 -24
- package/src/core/types/observable.mts +3 -3
- package/src/core/types/timer.mts +2 -0
- package/src/core/utils/id-maker.mts +4 -4
- package/src/globals.d.mts +0 -3
- package/src/utils/collect-to-array.mts +17 -0
- package/src/utils/create-boolean-state.mts +68 -0
- package/src/utils/create-event-emitter.mts +4 -4
- package/src/utils/create-reducer.mts +11 -8
- package/src/utils/create-state.mts +10 -75
- package/src/utils/index.mts +2 -0
- package/dist/core/create/from-array.d.mts +0 -39
- package/dist/core/create/from-array.d.mts.map +0 -1
- package/dist/core/create/from-array.mjs +0 -65
- package/dist/core/create/from-array.mjs.map +0 -1
- package/dist/core/create/interval.d.mts.map +0 -1
- package/dist/core/create/interval.mjs.map +0 -1
- package/dist/core/create/of.d.mts +0 -39
- package/dist/core/create/of.d.mts.map +0 -1
- package/dist/core/create/of.mjs +0 -63
- package/dist/core/create/of.mjs.map +0 -1
- package/dist/core/operators/audit-time.d.mts +0 -62
- package/dist/core/operators/audit-time.d.mts.map +0 -1
- package/dist/core/operators/audit-time.mjs +0 -109
- package/dist/core/operators/audit-time.mjs.map +0 -1
- package/dist/core/operators/debounce-time.d.mts +0 -51
- package/dist/core/operators/debounce-time.d.mts.map +0 -1
- package/dist/core/operators/debounce-time.mjs +0 -93
- package/dist/core/operators/debounce-time.mjs.map +0 -1
- package/dist/core/operators/map-with-index.d.mts +0 -54
- package/dist/core/operators/map-with-index.d.mts.map +0 -1
- package/dist/core/operators/map-with-index.mjs +0 -88
- package/dist/core/operators/map-with-index.mjs.map +0 -1
- package/dist/core/operators/throttle-time.d.mts +0 -62
- package/dist/core/operators/throttle-time.d.mts.map +0 -1
- package/dist/core/operators/throttle-time.mjs +0 -107
- package/dist/core/operators/throttle-time.mjs.map +0 -1
- package/src/core/create/from-array.mts +0 -76
- package/src/core/create/of.mts +0 -73
- package/src/core/operators/audit-time.mts +0 -136
- package/src/core/operators/debounce-time.mts +0 -116
- package/src/core/operators/map-with-index.mts +0 -183
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { asSafeUint, Optional, SafeUint } from 'ts-data-forge';
|
|
2
2
|
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
-
import { type
|
|
3
|
+
import { type CounterObservable, type TimerId } from '../types/index.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Creates an observable that emits incremental numbers at a specified interval.
|
|
7
7
|
* Starts with 0 immediately after subscription, then emits 1, 2, 3, ... every interval.
|
|
8
8
|
*
|
|
9
|
-
* @param
|
|
9
|
+
* @param intervalMilliSeconds - The interval duration in milliseconds
|
|
10
10
|
* @param startManually - If true, waits for manual start (default: false)
|
|
11
11
|
* @returns An observable that emits sequential numbers
|
|
12
12
|
*
|
|
@@ -18,16 +18,16 @@ import { type IntervalObservable } from '../types/index.mjs';
|
|
|
18
18
|
* // tick$ 0 1 2 3 4 5 ...
|
|
19
19
|
* //
|
|
20
20
|
* // Explanation:
|
|
21
|
-
* // -
|
|
21
|
+
* // - counter emits incrementing numbers at specified intervals
|
|
22
22
|
* // - Starts at 0 and continues indefinitely
|
|
23
23
|
* // - Useful for periodic tasks or animations
|
|
24
24
|
*
|
|
25
|
-
* const tick$ =
|
|
25
|
+
* const tick$ = counter(100);
|
|
26
26
|
*
|
|
27
|
-
* const
|
|
27
|
+
* const valueHistory: number[] = [];
|
|
28
28
|
*
|
|
29
29
|
* const subscription = tick$.subscribe((count) => {
|
|
30
|
-
*
|
|
30
|
+
* valueHistory.push(count);
|
|
31
31
|
* });
|
|
32
32
|
*
|
|
33
33
|
* await new Promise((resolve) => {
|
|
@@ -36,35 +36,40 @@ import { type IntervalObservable } from '../types/index.mjs';
|
|
|
36
36
|
*
|
|
37
37
|
* subscription.unsubscribe();
|
|
38
38
|
*
|
|
39
|
-
* assert.isTrue(Arr.isArrayAtLeastLength(
|
|
39
|
+
* assert.isTrue(Arr.isArrayAtLeastLength(valueHistory, 3));
|
|
40
40
|
*
|
|
41
|
-
* assert.deepStrictEqual(
|
|
41
|
+
* assert.deepStrictEqual(valueHistory[0], 0);
|
|
42
42
|
*
|
|
43
|
-
* assert.deepStrictEqual(
|
|
43
|
+
* assert.deepStrictEqual(valueHistory[1], 1);
|
|
44
44
|
*
|
|
45
|
-
* assert.deepStrictEqual(
|
|
45
|
+
* assert.deepStrictEqual(valueHistory[2], 2);
|
|
46
46
|
* ```
|
|
47
47
|
*/
|
|
48
|
-
export const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
export const counter = (
|
|
49
|
+
intervalMilliSeconds: number,
|
|
50
|
+
options?: Readonly<{
|
|
51
|
+
startManually?: boolean;
|
|
52
|
+
}>,
|
|
53
|
+
): CounterObservable =>
|
|
54
|
+
new CounterObservableClass(
|
|
55
|
+
intervalMilliSeconds,
|
|
56
|
+
options?.startManually ?? false,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
class CounterObservableClass
|
|
55
60
|
extends RootObservableClass<SafeUint>
|
|
56
|
-
implements
|
|
61
|
+
implements CounterObservable
|
|
57
62
|
{
|
|
58
|
-
readonly #
|
|
63
|
+
readonly #intervalMilliSeconds: number;
|
|
59
64
|
#mut_counter: SafeUint;
|
|
60
65
|
#mut_timerId0: TimerId | undefined;
|
|
61
66
|
#mut_timerId: TimerId | undefined;
|
|
62
67
|
#mut_isStarted: boolean;
|
|
63
68
|
|
|
64
|
-
constructor(
|
|
69
|
+
constructor(intervalMilliSeconds: number, startManually: boolean) {
|
|
65
70
|
super({ initialValue: Optional.none });
|
|
66
71
|
|
|
67
|
-
this.#
|
|
72
|
+
this.#intervalMilliSeconds = intervalMilliSeconds;
|
|
68
73
|
|
|
69
74
|
this.#mut_counter = asSafeUint(0);
|
|
70
75
|
|
|
@@ -74,27 +79,26 @@ class IntervalObservableClass
|
|
|
74
79
|
|
|
75
80
|
this.#mut_isStarted = false;
|
|
76
81
|
|
|
77
|
-
if (startManually
|
|
82
|
+
if (!startManually) {
|
|
78
83
|
this.start();
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
|
|
82
|
-
start():
|
|
87
|
+
start(): void {
|
|
83
88
|
if (this.#mut_isStarted) {
|
|
84
89
|
console.warn('cannot start twice');
|
|
85
90
|
|
|
86
|
-
return
|
|
91
|
+
return;
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
this.#mut_isStarted = true;
|
|
90
95
|
|
|
91
96
|
if (this.isCompleted) {
|
|
92
|
-
console.warn('cannot restart stopped
|
|
97
|
+
console.warn('cannot restart stopped CounterObservable');
|
|
93
98
|
|
|
94
|
-
return
|
|
99
|
+
return;
|
|
95
100
|
}
|
|
96
101
|
|
|
97
|
-
// emit zero
|
|
98
102
|
this.#mut_timerId0 = setTimeout(() => {
|
|
99
103
|
this.startUpdate(this.#mut_counter);
|
|
100
104
|
}, 0);
|
|
@@ -103,9 +107,7 @@ class IntervalObservableClass
|
|
|
103
107
|
this.#mut_counter = SafeUint.add(1, this.#mut_counter);
|
|
104
108
|
|
|
105
109
|
this.startUpdate(this.#mut_counter);
|
|
106
|
-
}, this.#
|
|
107
|
-
|
|
108
|
-
return this;
|
|
110
|
+
}, this.#intervalMilliSeconds);
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
#resetTimer(): void {
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Optional, Result } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { type FromPromiseObservable } from '../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an observable from a Promise factory that receives an `AbortSignal`.
|
|
7
|
+
* When the observable is completed (e.g., by `switchMap` switching to a new
|
|
8
|
+
* inner observable), the `AbortController` is automatically aborted, cancelling
|
|
9
|
+
* the in-flight request.
|
|
10
|
+
*
|
|
11
|
+
* Emits `Result.ok(value)` when the promise resolves, or `Result.err(error)`
|
|
12
|
+
* when it rejects. Rejections caused by abort (`AbortError`) are silently
|
|
13
|
+
* ignored and do not emit.
|
|
14
|
+
*
|
|
15
|
+
* @template A - The type of the resolved value
|
|
16
|
+
* @template E - The type of the error (excluding AbortError)
|
|
17
|
+
* @param factory - A function that receives an `AbortSignal` and returns a Promise
|
|
18
|
+
* @returns An observable that emits the promise result
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const results$ = query.pipe(
|
|
23
|
+
* switchMap((q) =>
|
|
24
|
+
* fromAbortablePromise((signal) =>
|
|
25
|
+
* fetch(`/api/search?q=${q}`, { signal }).then((r) => r.json()),
|
|
26
|
+
* ),
|
|
27
|
+
* ),
|
|
28
|
+
* );
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export const fromAbortablePromise = <A, E = unknown>(
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
33
|
+
factory: (signal: AbortSignal) => Promise<A>,
|
|
34
|
+
): FromPromiseObservable<A, E> =>
|
|
35
|
+
new FromAbortablePromiseObservableClass(factory);
|
|
36
|
+
|
|
37
|
+
class FromAbortablePromiseObservableClass<A, E = unknown>
|
|
38
|
+
extends RootObservableClass<Result<A, E>>
|
|
39
|
+
implements FromPromiseObservable<A, E>
|
|
40
|
+
{
|
|
41
|
+
readonly #abortController: AbortController;
|
|
42
|
+
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
44
|
+
constructor(factory: (signal: AbortSignal) => Promise<A>) {
|
|
45
|
+
super({ initialValue: Optional.none });
|
|
46
|
+
|
|
47
|
+
this.#abortController = new AbortController();
|
|
48
|
+
|
|
49
|
+
const promise = factory(this.#abortController.signal);
|
|
50
|
+
|
|
51
|
+
promise
|
|
52
|
+
.then((value) => {
|
|
53
|
+
if (this.isCompleted) return;
|
|
54
|
+
|
|
55
|
+
this.startUpdate(Result.ok(value));
|
|
56
|
+
})
|
|
57
|
+
.catch((error: unknown) => {
|
|
58
|
+
if (this.isCompleted) return;
|
|
59
|
+
|
|
60
|
+
// Silently ignore AbortError — it means the observable was
|
|
61
|
+
// intentionally completed (e.g., by switchMap).
|
|
62
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.startUpdate(
|
|
67
|
+
Result.err(
|
|
68
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
69
|
+
error as E,
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
})
|
|
73
|
+
.finally(() => {
|
|
74
|
+
this.complete();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
override complete(): void {
|
|
79
|
+
this.#abortController.abort();
|
|
80
|
+
|
|
81
|
+
super.complete();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -16,7 +16,7 @@ import { type FromPromiseObservable } from '../types/index.mjs';
|
|
|
16
16
|
* // Timeline:
|
|
17
17
|
* //
|
|
18
18
|
* // promise [pending...] -> resolved/rejected
|
|
19
|
-
* // data$
|
|
19
|
+
* // data$ Ok(value) or Err(error)
|
|
20
20
|
* //
|
|
21
21
|
* // Explanation:
|
|
22
22
|
* // - fromPromise converts a Promise into an observable
|
|
@@ -24,17 +24,20 @@ import { type FromPromiseObservable } from '../types/index.mjs';
|
|
|
24
24
|
* // - Completes after emitting the result
|
|
25
25
|
* // - Useful for integrating async operations into reactive flows
|
|
26
26
|
*
|
|
27
|
-
* const fetchData = async (): Promise<{ value: number }
|
|
27
|
+
* const fetchData = async (): Promise<Readonly<{ value: number }>> =>
|
|
28
|
+
* ({
|
|
29
|
+
* value: 42,
|
|
30
|
+
* }) as const;
|
|
28
31
|
*
|
|
29
32
|
* const data$ = fromPromise(fetchData());
|
|
30
33
|
*
|
|
31
|
-
* const
|
|
34
|
+
* const valueHistory: Readonly<{ value: number }>[] = [];
|
|
32
35
|
*
|
|
33
36
|
* await new Promise<void>((resolve) => {
|
|
34
37
|
* data$.subscribe(
|
|
35
38
|
* (result) => {
|
|
36
39
|
* if (Result.isOk(result)) {
|
|
37
|
-
*
|
|
40
|
+
* valueHistory.push(result.value);
|
|
38
41
|
* }
|
|
39
42
|
* },
|
|
40
43
|
* () => {
|
|
@@ -43,18 +46,18 @@ import { type FromPromiseObservable } from '../types/index.mjs';
|
|
|
43
46
|
* );
|
|
44
47
|
* });
|
|
45
48
|
*
|
|
46
|
-
* assert.deepStrictEqual(
|
|
49
|
+
* assert.deepStrictEqual(valueHistory, [{ value: 42 }]);
|
|
47
50
|
* ```
|
|
48
51
|
*/
|
|
49
52
|
export const fromPromise = <A, E = unknown>(
|
|
50
|
-
promise:
|
|
53
|
+
promise: Promise<A>,
|
|
51
54
|
): FromPromiseObservable<A, E> => new FromPromiseObservableClass(promise);
|
|
52
55
|
|
|
53
56
|
class FromPromiseObservableClass<A, E = unknown>
|
|
54
57
|
extends RootObservableClass<Result<A, E>>
|
|
55
58
|
implements FromPromiseObservable<A, E>
|
|
56
59
|
{
|
|
57
|
-
constructor(promise:
|
|
60
|
+
constructor(promise: Promise<A>) {
|
|
58
61
|
super({ initialValue: Optional.none });
|
|
59
62
|
|
|
60
63
|
promise
|
|
@@ -41,17 +41,17 @@ import {
|
|
|
41
41
|
*
|
|
42
42
|
* return { unsubscribe: () => {} };
|
|
43
43
|
* },
|
|
44
|
-
* };
|
|
44
|
+
* } as const;
|
|
45
45
|
*
|
|
46
46
|
* const observable$ = fromSubscribable<number>(customSubscribable);
|
|
47
47
|
*
|
|
48
|
-
* const
|
|
48
|
+
* const valueHistory: number[] = [];
|
|
49
49
|
*
|
|
50
50
|
* await new Promise<void>((resolve) => {
|
|
51
51
|
* observable$.subscribe(
|
|
52
52
|
* (result) => {
|
|
53
53
|
* if (Result.isOk(result)) {
|
|
54
|
-
*
|
|
54
|
+
* valueHistory.push(result.value);
|
|
55
55
|
* }
|
|
56
56
|
* },
|
|
57
57
|
* () => {
|
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
* );
|
|
61
61
|
* });
|
|
62
62
|
*
|
|
63
|
-
* assert.deepStrictEqual(
|
|
63
|
+
* assert.deepStrictEqual(valueHistory, [1, 2, 3]);
|
|
64
64
|
* ```
|
|
65
65
|
*/
|
|
66
66
|
export const fromSubscribable = <A, E = unknown>(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './counter.mjs';
|
|
2
|
+
export * from './from-abortable-promise.mjs';
|
|
2
3
|
export * from './from-promise.mjs';
|
|
3
4
|
export * from './from-subscribable.mjs';
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './of.mjs';
|
|
5
|
+
export * from './just.mjs';
|
|
6
6
|
export * from './source.mjs';
|
|
7
7
|
export * from './timer.mjs';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
+
import { type InitializedRootObservable } from '../types/index.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an Observable that holds a single static value and immediately
|
|
7
|
+
* completes. Useful inside `switchMap` to emit a fallback value when no
|
|
8
|
+
* asynchronous work is needed.
|
|
9
|
+
*
|
|
10
|
+
* @template A - The type of the value
|
|
11
|
+
* @param value - The value to emit
|
|
12
|
+
* @returns An initialized Observable that holds the value and is already completed
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const greeting$ = just('hello');
|
|
17
|
+
*
|
|
18
|
+
* const valueHistory: string[] = [];
|
|
19
|
+
*
|
|
20
|
+
* greeting$.subscribe(
|
|
21
|
+
* (value) => {
|
|
22
|
+
* valueHistory.push(value);
|
|
23
|
+
* },
|
|
24
|
+
* () => {
|
|
25
|
+
* // onComplete — called immediately since just() completes right away
|
|
26
|
+
* },
|
|
27
|
+
* );
|
|
28
|
+
*
|
|
29
|
+
* assert.deepStrictEqual(valueHistory, ['hello']);
|
|
30
|
+
*
|
|
31
|
+
* assert.strictEqual(greeting$.isCompleted, true);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const just = <const A,>(value: A): InitializedRootObservable<A> => {
|
|
35
|
+
const obs = new RootObservableClass<A>({
|
|
36
|
+
initialValue: Optional.some(value),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
obs.complete();
|
|
40
|
+
|
|
41
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
42
|
+
return obs as InitializedRootObservable<A>;
|
|
43
|
+
};
|
|
@@ -25,39 +25,35 @@ import {
|
|
|
25
25
|
*
|
|
26
26
|
* const count$ = source<number>();
|
|
27
27
|
*
|
|
28
|
-
* const
|
|
28
|
+
* const valueHistory: number[] = [];
|
|
29
29
|
*
|
|
30
30
|
* count$.subscribe((value) => {
|
|
31
|
-
*
|
|
31
|
+
* valueHistory.push(value);
|
|
32
32
|
* });
|
|
33
33
|
*
|
|
34
34
|
* count$.next(1); // logs: 1
|
|
35
35
|
*
|
|
36
|
-
* assert.deepStrictEqual(
|
|
36
|
+
* assert.deepStrictEqual(valueHistory, [1]);
|
|
37
37
|
*
|
|
38
38
|
* count$.next(2); // logs: 2
|
|
39
39
|
*
|
|
40
|
-
* assert.deepStrictEqual(
|
|
40
|
+
* assert.deepStrictEqual(valueHistory, [1, 2]);
|
|
41
41
|
*
|
|
42
42
|
* count$.next(3); // logs: 3
|
|
43
43
|
*
|
|
44
|
-
* assert.deepStrictEqual(
|
|
44
|
+
* assert.deepStrictEqual(valueHistory, [1, 2, 3]);
|
|
45
45
|
* ```
|
|
46
46
|
*/
|
|
47
|
-
export function source<A>(
|
|
47
|
+
export function source<const A>(
|
|
48
|
+
initialValue: A,
|
|
49
|
+
): InitializedSourceObservable<A>;
|
|
48
50
|
|
|
49
|
-
export function source<A>(): SourceObservable<A>;
|
|
51
|
+
export function source<const A>(): SourceObservable<A>;
|
|
50
52
|
|
|
51
|
-
export function source<A>(...args: readonly A[]): SourceObservable<A> {
|
|
53
|
+
export function source<const A>(...args: readonly A[]): SourceObservable<A> {
|
|
52
54
|
return new SourceObservableClass<A>(...args);
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
/**
|
|
56
|
-
* Alias for `source()`. Creates a new Observable source.
|
|
57
|
-
* @see source
|
|
58
|
-
*/
|
|
59
|
-
export const subject = source; // alias
|
|
60
|
-
|
|
61
57
|
class SourceObservableClass<A>
|
|
62
58
|
extends RootObservableClass<A>
|
|
63
59
|
implements SourceObservable<A>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Optional } from 'ts-data-forge';
|
|
2
2
|
import { RootObservableClass } from '../class/index.mjs';
|
|
3
|
-
import { type TimerObservable } from '../types/index.mjs';
|
|
3
|
+
import { type TimerId, type TimerObservable } from '../types/index.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Creates an observable that emits 0 after a specified delay and then completes.
|
|
@@ -22,12 +22,12 @@ import { type TimerObservable } from '../types/index.mjs';
|
|
|
22
22
|
*
|
|
23
23
|
* const delayed$ = timer(100);
|
|
24
24
|
*
|
|
25
|
-
* const
|
|
25
|
+
* const valueHistory: number[] = [];
|
|
26
26
|
*
|
|
27
27
|
* await new Promise<void>((resolve) => {
|
|
28
28
|
* delayed$.subscribe(
|
|
29
29
|
* () => {
|
|
30
|
-
*
|
|
30
|
+
* valueHistory.push(1);
|
|
31
31
|
* },
|
|
32
32
|
* () => {
|
|
33
33
|
* resolve();
|
|
@@ -35,13 +35,16 @@ import { type TimerObservable } from '../types/index.mjs';
|
|
|
35
35
|
* );
|
|
36
36
|
* });
|
|
37
37
|
*
|
|
38
|
-
* assert.deepStrictEqual(
|
|
38
|
+
* assert.deepStrictEqual(valueHistory, [1]);
|
|
39
39
|
* ```
|
|
40
40
|
*/
|
|
41
41
|
export const timer = (
|
|
42
42
|
milliSeconds: number,
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
options?: Readonly<{
|
|
44
|
+
startManually?: boolean;
|
|
45
|
+
}>,
|
|
46
|
+
): TimerObservable =>
|
|
47
|
+
new TimerObservableClass(milliSeconds, options?.startManually ?? false);
|
|
45
48
|
|
|
46
49
|
class TimerObservableClass
|
|
47
50
|
extends RootObservableClass<0>
|
|
@@ -65,11 +68,11 @@ class TimerObservableClass
|
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
|
|
68
|
-
start():
|
|
71
|
+
start(): void {
|
|
69
72
|
if (this.#mut_isStarted) {
|
|
70
73
|
console.warn('cannot start twice');
|
|
71
74
|
|
|
72
|
-
return
|
|
75
|
+
return;
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
this.#mut_isStarted = true;
|
|
@@ -77,7 +80,7 @@ class TimerObservableClass
|
|
|
77
80
|
if (this.isCompleted) {
|
|
78
81
|
console.warn('cannot restart stopped TimerObservable');
|
|
79
82
|
|
|
80
|
-
return
|
|
83
|
+
return;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
this.#mut_timerId = setTimeout(() => {
|
|
@@ -85,8 +88,6 @@ class TimerObservableClass
|
|
|
85
88
|
|
|
86
89
|
this.complete();
|
|
87
90
|
}, this.#milliSeconds);
|
|
88
|
-
|
|
89
|
-
return this;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
#resetTimer(): void {
|
package/src/core/index.mts
CHANGED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { Optional } from 'ts-data-forge';
|
|
2
|
+
import { AsyncChildObservableClass } from '../class/index.mjs';
|
|
3
|
+
import {
|
|
4
|
+
type AuditOperatorObservable,
|
|
5
|
+
type KeepInitialValueOperator,
|
|
6
|
+
type Observable,
|
|
7
|
+
type TimerId,
|
|
8
|
+
type UpdateToken,
|
|
9
|
+
} from '../types/index.mjs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Ignores source values for duration milliseconds, then emits the most recent value from the source Observable, then repeats this process.
|
|
13
|
+
*
|
|
14
|
+
* Unlike `throttle` which emits the first value, `audit` emits the last value.
|
|
15
|
+
*
|
|
16
|
+
* @template A - The type of values from the source
|
|
17
|
+
* @param milliSeconds - The audit time window in milliseconds
|
|
18
|
+
* @returns An operator that audits emissions from the observable
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Timeline (250ms audit):
|
|
23
|
+
* //
|
|
24
|
+
* // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
|
|
25
|
+
* //
|
|
26
|
+
* // input$ 0 2 3 9 10 11 12 13 14
|
|
27
|
+
* // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->
|
|
28
|
+
* // audited$ 2 3 11 14 (emitted at end of window)
|
|
29
|
+
* //
|
|
30
|
+
* // Explanation:
|
|
31
|
+
* // - audit emits the LAST value received during each time window
|
|
32
|
+
* // - Unlike throttle (which emits the FIRST value), audit emits the LAST
|
|
33
|
+
* // - Useful when you want the most recent value after a burst of events
|
|
34
|
+
*
|
|
35
|
+
* const input$ = source<number>();
|
|
36
|
+
*
|
|
37
|
+
* const audited$ = input$.pipe(audit(250));
|
|
38
|
+
*
|
|
39
|
+
* const valueHistory: number[] = [];
|
|
40
|
+
*
|
|
41
|
+
* audited$.subscribe((value) => {
|
|
42
|
+
* valueHistory.push(value);
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* const sleep = (ms: number): Promise<void> =>
|
|
46
|
+
* new Promise((resolve) => {
|
|
47
|
+
* setTimeout(resolve, ms);
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* input$.next(0);
|
|
51
|
+
*
|
|
52
|
+
* await sleep(200);
|
|
53
|
+
*
|
|
54
|
+
* input$.next(2);
|
|
55
|
+
*
|
|
56
|
+
* assert.deepStrictEqual(valueHistory, []);
|
|
57
|
+
*
|
|
58
|
+
* await sleep(100);
|
|
59
|
+
*
|
|
60
|
+
* assert.deepStrictEqual(valueHistory, [2]);
|
|
61
|
+
*
|
|
62
|
+
* input$.next(3);
|
|
63
|
+
*
|
|
64
|
+
* await sleep(300);
|
|
65
|
+
*
|
|
66
|
+
* assert.deepStrictEqual(valueHistory, [2, 3]);
|
|
67
|
+
*
|
|
68
|
+
* await sleep(300);
|
|
69
|
+
*
|
|
70
|
+
* input$.next(9);
|
|
71
|
+
*
|
|
72
|
+
* await sleep(100);
|
|
73
|
+
*
|
|
74
|
+
* input$.next(10);
|
|
75
|
+
*
|
|
76
|
+
* await sleep(100);
|
|
77
|
+
*
|
|
78
|
+
* input$.next(11);
|
|
79
|
+
*
|
|
80
|
+
* assert.deepStrictEqual(valueHistory, [2, 3]);
|
|
81
|
+
*
|
|
82
|
+
* await sleep(100);
|
|
83
|
+
*
|
|
84
|
+
* assert.deepStrictEqual(valueHistory, [2, 3, 11]);
|
|
85
|
+
*
|
|
86
|
+
* input$.next(12);
|
|
87
|
+
*
|
|
88
|
+
* await sleep(100);
|
|
89
|
+
*
|
|
90
|
+
* input$.next(13);
|
|
91
|
+
*
|
|
92
|
+
* assert.deepStrictEqual(valueHistory, [2, 3, 11]);
|
|
93
|
+
*
|
|
94
|
+
* await sleep(100);
|
|
95
|
+
*
|
|
96
|
+
* input$.next(14);
|
|
97
|
+
*
|
|
98
|
+
* assert.deepStrictEqual(valueHistory, [2, 3, 11]);
|
|
99
|
+
*
|
|
100
|
+
* await sleep(100);
|
|
101
|
+
*
|
|
102
|
+
* assert.deepStrictEqual(valueHistory, [2, 3, 11, 14]);
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export const audit = <A,>(
|
|
106
|
+
milliSeconds: number,
|
|
107
|
+
): KeepInitialValueOperator<A, A> =>
|
|
108
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
109
|
+
((parentObservable) =>
|
|
110
|
+
new AuditObservableClass(
|
|
111
|
+
parentObservable,
|
|
112
|
+
milliSeconds,
|
|
113
|
+
)) as KeepInitialValueOperator<A, A>;
|
|
114
|
+
|
|
115
|
+
class AuditObservableClass<A>
|
|
116
|
+
extends AsyncChildObservableClass<A, readonly [A]>
|
|
117
|
+
implements AuditOperatorObservable<A>
|
|
118
|
+
{
|
|
119
|
+
readonly #milliSeconds: number;
|
|
120
|
+
#mut_timerId: TimerId | undefined;
|
|
121
|
+
#mut_isSkipping: boolean;
|
|
122
|
+
|
|
123
|
+
constructor(parentObservable: Observable<A>, milliSeconds: number) {
|
|
124
|
+
super({
|
|
125
|
+
parents: [parentObservable],
|
|
126
|
+
initialValue: parentObservable.getSnapshot(),
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
this.#mut_isSkipping = false;
|
|
130
|
+
|
|
131
|
+
this.#mut_timerId = undefined;
|
|
132
|
+
|
|
133
|
+
this.#milliSeconds = milliSeconds;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
override tryUpdate(updateToken: UpdateToken): void {
|
|
137
|
+
const par = this.parents[0];
|
|
138
|
+
|
|
139
|
+
if (
|
|
140
|
+
par.updateToken !== updateToken ||
|
|
141
|
+
Optional.isNone(par.getSnapshot()) ||
|
|
142
|
+
this.#mut_isSkipping
|
|
143
|
+
) {
|
|
144
|
+
return; // skip update
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// set timer
|
|
148
|
+
this.#mut_isSkipping = true;
|
|
149
|
+
|
|
150
|
+
this.#mut_timerId = setTimeout(() => {
|
|
151
|
+
const sn = par.getSnapshot();
|
|
152
|
+
|
|
153
|
+
if (Optional.isNone(sn)) return;
|
|
154
|
+
|
|
155
|
+
this.startUpdate(sn.value);
|
|
156
|
+
|
|
157
|
+
this.#mut_isSkipping = false;
|
|
158
|
+
}, this.#milliSeconds);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
#resetTimer(): void {
|
|
162
|
+
if (this.#mut_timerId !== undefined) {
|
|
163
|
+
clearTimeout(this.#mut_timerId);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
override complete(): void {
|
|
168
|
+
this.#resetTimer();
|
|
169
|
+
|
|
170
|
+
super.complete();
|
|
171
|
+
}
|
|
172
|
+
}
|