synstate 0.1.0 → 0.1.2
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/LICENSE +201 -0
- package/README.md +272 -532
- package/assets/synstate-icon.png +0 -0
- package/dist/core/combine/combine.d.mts +33 -3
- package/dist/core/combine/combine.d.mts.map +1 -1
- package/dist/core/combine/combine.mjs +34 -4
- package/dist/core/combine/combine.mjs.map +1 -1
- package/dist/core/combine/merge.d.mts +30 -4
- package/dist/core/combine/merge.d.mts.map +1 -1
- package/dist/core/combine/merge.mjs +30 -4
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +28 -3
- package/dist/core/combine/zip.d.mts.map +1 -1
- package/dist/core/combine/zip.mjs +28 -3
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/from-array.d.mts +21 -3
- package/dist/core/create/from-array.d.mts.map +1 -1
- package/dist/core/create/from-array.mjs +21 -3
- package/dist/core/create/from-array.mjs.map +1 -1
- package/dist/core/create/from-promise.d.mts +29 -7
- package/dist/core/create/from-promise.d.mts.map +1 -1
- package/dist/core/create/from-promise.mjs +29 -7
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.d.mts +58 -0
- package/dist/core/create/from-subscribable.d.mts.map +1 -1
- package/dist/core/create/from-subscribable.mjs +58 -0
- package/dist/core/create/from-subscribable.mjs.map +1 -1
- package/dist/core/create/interval.d.mts +29 -4
- package/dist/core/create/interval.d.mts.map +1 -1
- package/dist/core/create/interval.mjs +29 -4
- package/dist/core/create/interval.mjs.map +1 -1
- package/dist/core/create/of.d.mts +22 -3
- package/dist/core/create/of.d.mts.map +1 -1
- package/dist/core/create/of.mjs +22 -3
- package/dist/core/create/of.mjs.map +1 -1
- package/dist/core/create/source.d.mts +21 -2
- package/dist/core/create/source.d.mts.map +1 -1
- package/dist/core/create/source.mjs +2 -2
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.d.mts +23 -4
- package/dist/core/create/timer.d.mts.map +1 -1
- package/dist/core/create/timer.mjs +23 -4
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/index.d.mts +1 -0
- package/dist/core/index.d.mts.map +1 -1
- package/dist/core/index.mjs +15 -3
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/operators/audit-time.d.mts +59 -0
- package/dist/core/operators/audit-time.d.mts.map +1 -1
- package/dist/core/operators/audit-time.mjs +59 -0
- package/dist/core/operators/audit-time.mjs.map +1 -1
- package/dist/core/operators/debounce-time.d.mts +22 -2
- package/dist/core/operators/debounce-time.d.mts.map +1 -1
- package/dist/core/operators/debounce-time.mjs +22 -2
- package/dist/core/operators/debounce-time.mjs.map +1 -1
- package/dist/core/operators/filter.d.mts +26 -1
- package/dist/core/operators/filter.d.mts.map +1 -1
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/index.mjs +3 -3
- package/dist/core/operators/map-with-index.d.mts +19 -17
- package/dist/core/operators/map-with-index.d.mts.map +1 -1
- package/dist/core/operators/map-with-index.mjs +21 -23
- package/dist/core/operators/map-with-index.mjs.map +1 -1
- package/dist/core/operators/merge-map.d.mts +48 -6
- package/dist/core/operators/merge-map.d.mts.map +1 -1
- package/dist/core/operators/merge-map.mjs +48 -6
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.d.mts +30 -1
- package/dist/core/operators/pairwise.d.mts.map +1 -1
- package/dist/core/operators/pairwise.mjs +30 -1
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.d.mts +23 -1
- package/dist/core/operators/scan.d.mts.map +1 -1
- package/dist/core/operators/scan.mjs +23 -1
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.d.mts +26 -2
- package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs +27 -3
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.d.mts +50 -0
- package/dist/core/operators/skip-until.d.mts.map +1 -1
- package/dist/core/operators/skip-until.mjs +50 -0
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.d.mts +48 -1
- package/dist/core/operators/skip-while.d.mts.map +1 -1
- package/dist/core/operators/skip-while.mjs +50 -5
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.d.mts +39 -5
- package/dist/core/operators/switch-map.d.mts.map +1 -1
- package/dist/core/operators/switch-map.mjs +39 -5
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.d.mts +20 -1
- package/dist/core/operators/take-until.d.mts.map +1 -1
- package/dist/core/operators/take-until.mjs +20 -1
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.d.mts +47 -1
- package/dist/core/operators/take-while.d.mts.map +1 -1
- package/dist/core/operators/take-while.mjs +48 -3
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/throttle-time.d.mts +44 -5
- package/dist/core/operators/throttle-time.d.mts.map +1 -1
- package/dist/core/operators/throttle-time.mjs +44 -5
- package/dist/core/operators/throttle-time.mjs.map +1 -1
- package/dist/core/operators/with-buffered-from.d.mts +57 -0
- package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs +58 -1
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.d.mts +59 -0
- package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs +60 -1
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.d.mts +24 -2
- package/dist/core/operators/with-initial-value.d.mts.map +1 -1
- package/dist/core/operators/with-initial-value.mjs +24 -2
- 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 +13 -0
- package/dist/core/predefined/index.mjs.map +1 -0
- package/dist/core/predefined/operators/attach-index.d.mts +8 -0
- package/dist/core/predefined/operators/attach-index.d.mts.map +1 -0
- package/dist/core/predefined/operators/attach-index.mjs +13 -0
- package/dist/core/predefined/operators/attach-index.mjs.map +1 -0
- package/dist/core/predefined/operators/index.d.mts +13 -0
- package/dist/core/predefined/operators/index.d.mts.map +1 -0
- package/dist/core/predefined/operators/index.mjs +13 -0
- package/dist/core/predefined/operators/index.mjs.map +1 -0
- package/dist/core/predefined/operators/map-optional.d.mts +4 -0
- package/dist/core/predefined/operators/map-optional.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-optional.mjs +7 -0
- package/dist/core/predefined/operators/map-optional.mjs.map +1 -0
- package/dist/core/predefined/operators/map-result-err.d.mts +4 -0
- package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-result-err.mjs +7 -0
- package/dist/core/predefined/operators/map-result-err.mjs.map +1 -0
- package/dist/core/predefined/operators/map-result-ok.d.mts +4 -0
- package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-result-ok.mjs +7 -0
- package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -0
- package/dist/core/predefined/operators/map-to.d.mts +3 -0
- package/dist/core/predefined/operators/map-to.d.mts.map +1 -0
- package/dist/core/predefined/operators/map-to.mjs +6 -0
- package/dist/core/predefined/operators/map-to.mjs.map +1 -0
- package/dist/core/predefined/operators/map.d.mts +3 -0
- package/dist/core/predefined/operators/map.d.mts.map +1 -0
- package/dist/core/predefined/operators/map.mjs +8 -0
- package/dist/core/predefined/operators/map.mjs.map +1 -0
- package/dist/core/predefined/operators/pluck.d.mts +8 -0
- package/dist/core/predefined/operators/pluck.d.mts.map +1 -0
- package/dist/core/predefined/operators/pluck.mjs +11 -0
- package/dist/core/predefined/operators/pluck.mjs.map +1 -0
- package/dist/core/predefined/operators/skip.d.mts +3 -0
- package/dist/core/predefined/operators/skip.d.mts.map +1 -0
- package/dist/core/predefined/operators/skip.mjs +9 -0
- package/dist/core/predefined/operators/skip.mjs.map +1 -0
- package/dist/core/predefined/operators/take.d.mts +3 -0
- package/dist/core/predefined/operators/take.d.mts.map +1 -0
- package/dist/core/predefined/operators/take.mjs +8 -0
- package/dist/core/predefined/operators/take.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-optional.d.mts +4 -0
- package/dist/core/predefined/operators/unwrap-optional.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-optional.mjs +9 -0
- package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-err.d.mts +4 -0
- package/dist/core/predefined/operators/unwrap-result-err.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-err.mjs +7 -0
- package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts +4 -0
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts.map +1 -0
- package/dist/core/predefined/operators/unwrap-result-ok.mjs +9 -0
- package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -0
- package/dist/core/types/observable-family.d.mts +7 -7
- package/dist/entry-point.mjs +15 -3
- package/dist/entry-point.mjs.map +1 -1
- package/dist/index.mjs +15 -3
- package/dist/index.mjs.map +1 -1
- package/dist/utils/create-event-emitter.d.mts +20 -2
- package/dist/utils/create-event-emitter.d.mts.map +1 -1
- package/dist/utils/create-event-emitter.mjs +20 -2
- package/dist/utils/create-event-emitter.mjs.map +1 -1
- package/dist/utils/create-reducer.d.mts +13 -1
- package/dist/utils/create-reducer.d.mts.map +1 -1
- package/dist/utils/create-reducer.mjs +13 -1
- package/dist/utils/create-reducer.mjs.map +1 -1
- package/dist/utils/create-state.d.mts +24 -4
- package/dist/utils/create-state.d.mts.map +1 -1
- package/dist/utils/create-state.mjs +24 -4
- package/dist/utils/create-state.mjs.map +1 -1
- package/package.json +13 -12
- package/src/core/combine/combine.mts +34 -4
- package/src/core/combine/merge.mts +30 -4
- package/src/core/combine/zip.mts +28 -3
- package/src/core/create/from-array.mts +21 -3
- package/src/core/create/from-promise.mts +29 -7
- package/src/core/create/from-subscribable.mts +58 -0
- package/src/core/create/interval.mts +29 -4
- package/src/core/create/of.mts +22 -3
- package/src/core/create/source.mts +22 -3
- package/src/core/create/timer.mts +23 -4
- package/src/core/index.mts +1 -0
- package/src/core/operators/audit-time.mts +59 -0
- package/src/core/operators/debounce-time.mts +22 -2
- package/src/core/operators/filter.mts +26 -1
- package/src/core/operators/map-with-index.mts +22 -66
- package/src/core/operators/merge-map.mts +48 -6
- package/src/core/operators/pairwise.mts +30 -1
- package/src/core/operators/scan.mts +23 -1
- package/src/core/operators/skip-if-no-change.mts +27 -3
- package/src/core/operators/skip-until.mts +50 -0
- package/src/core/operators/skip-while.mts +49 -16
- package/src/core/operators/switch-map.mts +39 -5
- package/src/core/operators/take-until.mts +20 -1
- package/src/core/operators/take-while.mts +49 -8
- package/src/core/operators/throttle-time.mts +44 -5
- package/src/core/operators/with-buffered-from.mts +58 -1
- package/src/core/operators/with-current-value-from.mts +60 -1
- package/src/core/operators/with-initial-value.mts +24 -2
- package/src/core/predefined/index.mts +1 -0
- package/src/core/predefined/operators/attach-index.mts +13 -0
- package/src/core/predefined/operators/index.mts +12 -0
- package/src/core/predefined/operators/map-optional.mts +8 -0
- package/src/core/predefined/operators/map-result-err.mts +8 -0
- package/src/core/predefined/operators/map-result-ok.mts +8 -0
- package/src/core/predefined/operators/map-to.mts +5 -0
- package/src/core/predefined/operators/map.mts +5 -0
- package/src/core/predefined/operators/pluck.mts +12 -0
- package/src/core/predefined/operators/skip.mts +10 -0
- package/src/core/predefined/operators/take.mts +6 -0
- package/src/core/predefined/operators/unwrap-optional.mts +9 -0
- package/src/core/predefined/operators/unwrap-result-err.mts +8 -0
- package/src/core/predefined/operators/unwrap-result-ok.mts +9 -0
- package/src/core/types/observable-family.mts +7 -7
- package/src/utils/create-event-emitter.mts +20 -2
- package/src/utils/create-reducer.mts +13 -1
- package/src/utils/create-state.mts +24 -4
|
@@ -7,6 +7,65 @@ import {
|
|
|
7
7
|
type UpdaterSymbol,
|
|
8
8
|
} from '../types/index.mjs';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Emits the last value from the source observable after a specified time window has passed.
|
|
12
|
+
* Unlike throttleTime which emits the first value, auditTime emits the last value.
|
|
13
|
+
*
|
|
14
|
+
* @template A - The type of values from the source
|
|
15
|
+
* @param milliSeconds - The audit time window in milliseconds
|
|
16
|
+
* @returns An operator that audits emissions from the observable
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // Timeline (1000ms audit):
|
|
21
|
+
* //
|
|
22
|
+
* // Time(ms) 0 100 200 300 400 ... 1000 1100
|
|
23
|
+
* // input$ e1 e2 e3 e4 e5
|
|
24
|
+
* // audited$ e5 (emitted at end of window)
|
|
25
|
+
* // |-------1000ms window------> ^
|
|
26
|
+
* //
|
|
27
|
+
* // Explanation:
|
|
28
|
+
* // - auditTime emits the LAST value received during each time window
|
|
29
|
+
* // - Unlike throttleTime (which emits the FIRST value), audit emits the LAST
|
|
30
|
+
* // - At 0-1000ms: e1-e5 are received
|
|
31
|
+
* // - At 1000ms: e5 (the last value in the window) is emitted
|
|
32
|
+
* // - Useful when you want the most recent value after a burst of events
|
|
33
|
+
*
|
|
34
|
+
* const input$ = source<number>();
|
|
35
|
+
*
|
|
36
|
+
* const audited$ = input$.pipe(auditTime(200));
|
|
37
|
+
*
|
|
38
|
+
* const mut_history: number[] = [];
|
|
39
|
+
*
|
|
40
|
+
* audited$.subscribe((value) => {
|
|
41
|
+
* mut_history.push(value);
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* input$.next(1);
|
|
45
|
+
*
|
|
46
|
+
* input$.next(2);
|
|
47
|
+
*
|
|
48
|
+
* input$.next(3);
|
|
49
|
+
*
|
|
50
|
+
* assert.deepStrictEqual(mut_history, []);
|
|
51
|
+
*
|
|
52
|
+
* await new Promise((resolve) => {
|
|
53
|
+
* setTimeout(resolve, 250);
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* assert.deepStrictEqual(mut_history, [3]);
|
|
57
|
+
*
|
|
58
|
+
* input$.next(4);
|
|
59
|
+
*
|
|
60
|
+
* input$.next(5);
|
|
61
|
+
*
|
|
62
|
+
* await new Promise((resolve) => {
|
|
63
|
+
* setTimeout(resolve, 250);
|
|
64
|
+
* });
|
|
65
|
+
*
|
|
66
|
+
* assert.deepStrictEqual(mut_history, [3, 5]);
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
10
69
|
export const auditTime = <A,>(
|
|
11
70
|
milliSeconds: number,
|
|
12
71
|
): KeepInitialValueOperator<A, A> =>
|
|
@@ -17,12 +17,27 @@ import {
|
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* ```ts
|
|
20
|
+
* // Timeline (300ms debounce):
|
|
21
|
+
* //
|
|
22
|
+
* // Time(ms) 0 100 200 300 400 500 600 ... 900 1000
|
|
23
|
+
* // input$ 'h' 'he' 'hel' 'hello'
|
|
24
|
+
* // debounced$ 'hello' (emitted after 300ms silence)
|
|
25
|
+
* //
|
|
26
|
+
* // Explanation:
|
|
27
|
+
* // - At 0ms: 'h' is emitted, timer starts
|
|
28
|
+
* // - At 100ms: 'he' is emitted, timer resets
|
|
29
|
+
* // - At 200ms: 'hel' is emitted, timer resets
|
|
30
|
+
* // - At 300ms: 'hello' is emitted, timer resets
|
|
31
|
+
* // - At 600ms: No new emission for 300ms, 'hello' is finally emitted
|
|
32
|
+
*
|
|
20
33
|
* const input$ = source<string>();
|
|
21
34
|
*
|
|
22
35
|
* const debounced$ = input$.pipe(debounceTime(300));
|
|
23
36
|
*
|
|
37
|
+
* const mut_history: string[] = [];
|
|
38
|
+
*
|
|
24
39
|
* debounced$.subscribe((value) => {
|
|
25
|
-
*
|
|
40
|
+
* mut_history.push(value);
|
|
26
41
|
* });
|
|
27
42
|
*
|
|
28
43
|
* input$.next('h');
|
|
@@ -32,7 +47,12 @@ import {
|
|
|
32
47
|
* input$.next('hel');
|
|
33
48
|
*
|
|
34
49
|
* input$.next('hello');
|
|
35
|
-
*
|
|
50
|
+
*
|
|
51
|
+
* await new Promise((resolve) => {
|
|
52
|
+
* setTimeout(resolve, 400);
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* assert.deepStrictEqual(mut_history, ['hello']);
|
|
36
56
|
* ```
|
|
37
57
|
*/
|
|
38
58
|
export const debounceTime = <A,>(
|
|
@@ -27,17 +27,42 @@ import { withInitialValue } from './with-initial-value.mjs';
|
|
|
27
27
|
*
|
|
28
28
|
* @example
|
|
29
29
|
* ```ts
|
|
30
|
+
* // Timeline:
|
|
31
|
+
* //
|
|
32
|
+
* // num$ 1 2 3 4 5 6
|
|
33
|
+
* // even$ 2 4 6
|
|
34
|
+
* //
|
|
35
|
+
* // Explanation:
|
|
36
|
+
* // - filter passes through only values that satisfy the predicate
|
|
37
|
+
* // - Only even numbers (2, 4, 6) are emitted
|
|
38
|
+
*
|
|
30
39
|
* const num$ = source<number>();
|
|
31
40
|
*
|
|
32
41
|
* const even$ = num$.pipe(filter((x) => x % 2 === 0));
|
|
33
42
|
*
|
|
43
|
+
* const mut_history: number[] = [];
|
|
44
|
+
*
|
|
34
45
|
* even$.subscribe((x) => {
|
|
35
|
-
*
|
|
46
|
+
* mut_history.push(x);
|
|
36
47
|
* });
|
|
37
48
|
*
|
|
38
49
|
* num$.next(1); // nothing logged
|
|
39
50
|
*
|
|
40
51
|
* num$.next(2); // logs: 2
|
|
52
|
+
*
|
|
53
|
+
* assert.deepStrictEqual(mut_history, [2]);
|
|
54
|
+
*
|
|
55
|
+
* num$.next(3); // nothing logged
|
|
56
|
+
*
|
|
57
|
+
* num$.next(4); // logs: 4
|
|
58
|
+
*
|
|
59
|
+
* assert.deepStrictEqual(mut_history, [2, 4]);
|
|
60
|
+
*
|
|
61
|
+
* num$.next(5);
|
|
62
|
+
*
|
|
63
|
+
* num$.next(6);
|
|
64
|
+
*
|
|
65
|
+
* assert.deepStrictEqual(mut_history, [2, 4, 6]);
|
|
41
66
|
* ```
|
|
42
67
|
*/
|
|
43
68
|
export function filter<A, B extends A>(
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Optional,
|
|
3
|
-
Result,
|
|
4
|
-
SafeUint,
|
|
5
|
-
asSafeUint,
|
|
6
|
-
expectType,
|
|
7
|
-
} from 'ts-data-forge';
|
|
1
|
+
import { Optional, SafeUint, asSafeUint, expectType } from 'ts-data-forge';
|
|
8
2
|
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
9
3
|
import { source } from '../create/index.mjs';
|
|
10
4
|
import {
|
|
@@ -26,17 +20,32 @@ import { withInitialValue } from './with-initial-value.mjs';
|
|
|
26
20
|
*
|
|
27
21
|
* @example
|
|
28
22
|
* ```ts
|
|
29
|
-
*
|
|
23
|
+
* // Timeline:
|
|
24
|
+
* //
|
|
25
|
+
* // num$ "a" "b" "c"
|
|
26
|
+
* // indexed$ "0: a" "1: b" "2: c"
|
|
27
|
+
* //
|
|
28
|
+
* // Explanation:
|
|
29
|
+
* // - mapWithIndex transforms each value along with its index
|
|
30
|
+
* // - Index starts at 0 and increments with each emission
|
|
31
|
+
*
|
|
32
|
+
* const num$ = source<string>();
|
|
30
33
|
*
|
|
31
34
|
* const indexed$ = num$.pipe(mapWithIndex((x, i) => `${i}: ${x}`));
|
|
32
35
|
*
|
|
36
|
+
* const mut_history: string[] = [];
|
|
37
|
+
*
|
|
33
38
|
* indexed$.subscribe((s) => {
|
|
34
|
-
*
|
|
39
|
+
* mut_history.push(s);
|
|
35
40
|
* });
|
|
36
41
|
*
|
|
37
|
-
* num$.next(
|
|
42
|
+
* num$.next('a'); // 0: a
|
|
43
|
+
*
|
|
44
|
+
* num$.next('b'); // 1: b
|
|
45
|
+
*
|
|
46
|
+
* num$.next('c'); // 2: c
|
|
38
47
|
*
|
|
39
|
-
*
|
|
48
|
+
* assert.deepStrictEqual(mut_history, ['0: a', '1: b', '2: c']);
|
|
40
49
|
* ```
|
|
41
50
|
*/
|
|
42
51
|
export const mapWithIndex = <A, B>(
|
|
@@ -49,59 +58,6 @@ export const mapWithIndex = <A, B>(
|
|
|
49
58
|
mapFn,
|
|
50
59
|
)) as KeepInitialValueOperator<A, B>;
|
|
51
60
|
|
|
52
|
-
/* Specialized operators */
|
|
53
|
-
|
|
54
|
-
export const map = <A, B>(mapFn: (x: A) => B): KeepInitialValueOperator<A, B> =>
|
|
55
|
-
mapWithIndex(mapFn);
|
|
56
|
-
|
|
57
|
-
export const mapTo = <A, B>(value: B): KeepInitialValueOperator<A, B> =>
|
|
58
|
-
map(() => value);
|
|
59
|
-
|
|
60
|
-
export const pluck = <A, K extends keyof A>(
|
|
61
|
-
key: K,
|
|
62
|
-
): KeepInitialValueOperator<A, A[K]> => map((a) => a[key]);
|
|
63
|
-
|
|
64
|
-
export const getKey = pluck; // alias
|
|
65
|
-
|
|
66
|
-
export const attachIndex = <A,>(): KeepInitialValueOperator<
|
|
67
|
-
A,
|
|
68
|
-
readonly [SafeUint | -1, A]
|
|
69
|
-
> => mapWithIndex((a, i) => [i, a] as const);
|
|
70
|
-
|
|
71
|
-
export const withIndex = attachIndex; // alias
|
|
72
|
-
|
|
73
|
-
export const unwrapOptional = <
|
|
74
|
-
O extends UnknownOptional,
|
|
75
|
-
>(): KeepInitialValueOperator<O, Optional.Unwrap<O> | undefined> =>
|
|
76
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
77
|
-
map(Optional.unwrap as Fn<O, Optional.Unwrap<O> | undefined>);
|
|
78
|
-
|
|
79
|
-
export const unwrapResultOk = <
|
|
80
|
-
R extends UnknownResult,
|
|
81
|
-
>(): KeepInitialValueOperator<R, Result.UnwrapOk<R> | undefined> =>
|
|
82
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
83
|
-
map(Result.unwrapOk as Fn<R, Result.UnwrapOk<R> | undefined>);
|
|
84
|
-
|
|
85
|
-
export const unwrapResultErr = <
|
|
86
|
-
R extends UnknownResult,
|
|
87
|
-
>(): KeepInitialValueOperator<R, Result.UnwrapErr<R> | undefined> =>
|
|
88
|
-
map(Result.unwrapErr as Fn<R, Result.UnwrapErr<R> | undefined>);
|
|
89
|
-
|
|
90
|
-
export const mapOptional = <O extends UnknownOptional, B>(
|
|
91
|
-
mapFn: (x: Optional.Unwrap<O>) => B,
|
|
92
|
-
): KeepInitialValueOperator<O, Optional<B>> =>
|
|
93
|
-
map((a) => Optional.map(a, mapFn));
|
|
94
|
-
|
|
95
|
-
export const mapResultOk = <R extends UnknownResult, S2>(
|
|
96
|
-
mapFn: (x: Result.UnwrapOk<R>) => S2,
|
|
97
|
-
): KeepInitialValueOperator<R, Result<S2, Result.UnwrapErr<R>>> =>
|
|
98
|
-
map((a) => Result.map(a, mapFn));
|
|
99
|
-
|
|
100
|
-
export const mapResultErr = <R extends UnknownResult, E2>(
|
|
101
|
-
mapFn: (x: Result.UnwrapErr<R>) => E2,
|
|
102
|
-
): KeepInitialValueOperator<R, Result<Result.UnwrapOk<R>, E2>> =>
|
|
103
|
-
map((a) => Result.mapErr(a, mapFn));
|
|
104
|
-
|
|
105
61
|
/* implementation */
|
|
106
62
|
|
|
107
63
|
class MapWithIndexObservableClass<A, B>
|
|
@@ -151,7 +107,7 @@ if (import.meta.vitest !== undefined) {
|
|
|
151
107
|
{
|
|
152
108
|
const s: Observable<number> = source<number>();
|
|
153
109
|
|
|
154
|
-
const _d1 = s.pipe(
|
|
110
|
+
const _d1 = s.pipe(mapWithIndex((x, i) => x + i));
|
|
155
111
|
|
|
156
112
|
expectType<typeof _d1, Observable<number>>('=');
|
|
157
113
|
}
|
|
@@ -161,7 +117,7 @@ if (import.meta.vitest !== undefined) {
|
|
|
161
117
|
|
|
162
118
|
const m: InitializedObservable<number> = s.pipe(withInitialValue(0));
|
|
163
119
|
|
|
164
|
-
const _d = m.pipe(
|
|
120
|
+
const _d = m.pipe(mapWithIndex((x, i) => x + i));
|
|
165
121
|
|
|
166
122
|
expectType<typeof _d, InitializedObservable<number>>('=');
|
|
167
123
|
}
|
|
@@ -19,16 +19,58 @@ import {
|
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* ```ts
|
|
22
|
+
* // Timeline:
|
|
23
|
+
* //
|
|
24
|
+
* // ids$ 1 2 3
|
|
25
|
+
* // requests fetch(1) fetch(2) fetch(3)
|
|
26
|
+
* // users$ result1 result2 result3
|
|
27
|
+
* // (parallel) (parallel) (parallel)
|
|
28
|
+
* //
|
|
29
|
+
* // Explanation:
|
|
30
|
+
* // - mergeMap runs all inner observables in parallel
|
|
31
|
+
* // - Results are emitted as they arrive (may be out of order)
|
|
32
|
+
* // - Does NOT cancel previous requests
|
|
33
|
+
* // - All requests run concurrently and all results are emitted
|
|
34
|
+
*
|
|
22
35
|
* const ids$ = source<number>();
|
|
23
36
|
*
|
|
24
|
-
* const users$ = ids$.pipe(
|
|
37
|
+
* const users$ = ids$.pipe(
|
|
38
|
+
* mergeMap((id) => {
|
|
39
|
+
* const result$ = source<{ id: number }>();
|
|
40
|
+
*
|
|
41
|
+
* setTimeout(() => {
|
|
42
|
+
* result$.next({ id });
|
|
43
|
+
*
|
|
44
|
+
* result$.complete();
|
|
45
|
+
* }, 10);
|
|
46
|
+
*
|
|
47
|
+
* return result$;
|
|
48
|
+
* }),
|
|
49
|
+
* );
|
|
25
50
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
51
|
+
* const mut_history: { id: number }[] = [];
|
|
52
|
+
*
|
|
53
|
+
* users$.subscribe((value) => {
|
|
54
|
+
* mut_history.push(value);
|
|
28
55
|
* });
|
|
29
|
-
* // All requests run in parallel, results merged as they arrive
|
|
30
56
|
*
|
|
31
|
-
*
|
|
57
|
+
* ids$.next(1);
|
|
58
|
+
*
|
|
59
|
+
* ids$.next(2);
|
|
60
|
+
*
|
|
61
|
+
* ids$.next(3);
|
|
62
|
+
*
|
|
63
|
+
* await new Promise((resolve) => {
|
|
64
|
+
* setTimeout(resolve, 200);
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* assert.deepStrictEqual(mut_history.length, 3);
|
|
68
|
+
*
|
|
69
|
+
* assert.isTrue(mut_history.some((u) => u.id === 1));
|
|
70
|
+
*
|
|
71
|
+
* assert.isTrue(mut_history.some((u) => u.id === 2));
|
|
72
|
+
*
|
|
73
|
+
* assert.isTrue(mut_history.some((u) => u.id === 3));
|
|
32
74
|
* ```
|
|
33
75
|
*
|
|
34
76
|
* @note To improve code readability, consider using `createState` instead of `mergeMap`,
|
|
@@ -42,7 +84,7 @@ export const mergeMap =
|
|
|
42
84
|
new MergeMapObservableClass(parentObservable, mapToObservable);
|
|
43
85
|
|
|
44
86
|
/**
|
|
45
|
-
* Alias for `mergeMap
|
|
87
|
+
* Alias for `mergeMap`.
|
|
46
88
|
* @see mergeMap
|
|
47
89
|
*/
|
|
48
90
|
export const flatMap = mergeMap;
|
|
@@ -16,19 +16,48 @@ import {
|
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* ```ts
|
|
19
|
+
* // Timeline:
|
|
20
|
+
* //
|
|
21
|
+
* // num$ 1 2 3 4
|
|
22
|
+
* // pairs$ [1,2] [2,3] [3,4]
|
|
23
|
+
* //
|
|
24
|
+
* // Explanation:
|
|
25
|
+
* // - pairwise emits the current and previous values as a tuple
|
|
26
|
+
* // - Nothing is emitted for the first value (no previous value yet)
|
|
27
|
+
* // - Useful for tracking changes between consecutive values
|
|
28
|
+
*
|
|
19
29
|
* const num$ = source<number>();
|
|
20
30
|
*
|
|
21
31
|
* const pairs$ = num$.pipe(pairwise());
|
|
22
32
|
*
|
|
33
|
+
* const mut_history: (readonly [number, number])[] = [];
|
|
34
|
+
*
|
|
23
35
|
* pairs$.subscribe(([prev, curr]) => {
|
|
24
|
-
*
|
|
36
|
+
* mut_history.push([prev, curr]);
|
|
25
37
|
* });
|
|
26
38
|
*
|
|
27
39
|
* num$.next(1); // nothing logged
|
|
28
40
|
*
|
|
41
|
+
* assert.deepStrictEqual(mut_history, []);
|
|
42
|
+
*
|
|
29
43
|
* num$.next(2); // logs: 1, 2
|
|
30
44
|
*
|
|
45
|
+
* assert.deepStrictEqual(mut_history, [[1, 2]]);
|
|
46
|
+
*
|
|
31
47
|
* num$.next(3); // logs: 2, 3
|
|
48
|
+
*
|
|
49
|
+
* assert.deepStrictEqual(mut_history, [
|
|
50
|
+
* [1, 2],
|
|
51
|
+
* [2, 3],
|
|
52
|
+
* ]);
|
|
53
|
+
*
|
|
54
|
+
* num$.next(4); // logs: 3, 4
|
|
55
|
+
*
|
|
56
|
+
* assert.deepStrictEqual(mut_history, [
|
|
57
|
+
* [1, 2],
|
|
58
|
+
* [2, 3],
|
|
59
|
+
* [3, 4],
|
|
60
|
+
* ]);
|
|
32
61
|
* ```
|
|
33
62
|
*/
|
|
34
63
|
export const pairwise = <A,>(): DropInitialValueOperator<A, readonly [A, A]> =>
|
|
@@ -19,19 +19,41 @@ import {
|
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* ```ts
|
|
22
|
+
* // Timeline (accumulating sum):
|
|
23
|
+
* //
|
|
24
|
+
* // num$ 1 2 3 4 5
|
|
25
|
+
* // sum$ 1 3 6 10 15
|
|
26
|
+
* // | | | | |
|
|
27
|
+
* // 0+1 1+2 3+3 6+4 10+5
|
|
28
|
+
* //
|
|
29
|
+
* // Explanation:
|
|
30
|
+
* // - scan accumulates values over time using a reducer function
|
|
31
|
+
* // - Starting with seed value 0, each emission adds to the accumulator
|
|
32
|
+
* // - Similar to Array.reduce, but for streams
|
|
33
|
+
*
|
|
22
34
|
* const num$ = source<number>();
|
|
23
35
|
*
|
|
24
36
|
* const sum$ = num$.pipe(scan((acc, curr) => acc + curr, 0));
|
|
25
37
|
*
|
|
38
|
+
* const mut_history: number[] = [];
|
|
39
|
+
*
|
|
26
40
|
* sum$.subscribe((x) => {
|
|
27
|
-
*
|
|
41
|
+
* mut_history.push(x);
|
|
28
42
|
* });
|
|
29
43
|
*
|
|
44
|
+
* assert.deepStrictEqual(mut_history, [0]);
|
|
45
|
+
*
|
|
30
46
|
* num$.next(1); // logs: 1
|
|
31
47
|
*
|
|
48
|
+
* assert.deepStrictEqual(mut_history, [0, 1]);
|
|
49
|
+
*
|
|
32
50
|
* num$.next(2); // logs: 3
|
|
33
51
|
*
|
|
52
|
+
* assert.deepStrictEqual(mut_history, [0, 1, 3]);
|
|
53
|
+
*
|
|
34
54
|
* num$.next(3); // logs: 6
|
|
55
|
+
*
|
|
56
|
+
* assert.deepStrictEqual(mut_history, [0, 1, 3, 6]);
|
|
35
57
|
* ```
|
|
36
58
|
*/
|
|
37
59
|
export const scan =
|
|
@@ -17,19 +17,43 @@ import {
|
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* ```ts
|
|
20
|
+
* // Timeline:
|
|
21
|
+
* //
|
|
22
|
+
* // num$ 1 1 2 2 2 3
|
|
23
|
+
* // distinct$ 1 2 3
|
|
24
|
+
* //
|
|
25
|
+
* // Explanation:
|
|
26
|
+
* // - skipIfNoChange filters out consecutive duplicate values
|
|
27
|
+
* // - Uses strict equality (===) for comparison
|
|
28
|
+
* // - Only emits when the value actually changes
|
|
29
|
+
*
|
|
20
30
|
* const num$ = source<number>();
|
|
21
31
|
*
|
|
22
32
|
* const distinct$ = num$.pipe(skipIfNoChange());
|
|
23
33
|
*
|
|
34
|
+
* const mut_history: number[] = [];
|
|
35
|
+
*
|
|
24
36
|
* distinct$.subscribe((x) => {
|
|
25
|
-
*
|
|
37
|
+
* mut_history.push(x);
|
|
26
38
|
* });
|
|
27
39
|
*
|
|
28
40
|
* num$.next(1); // logs: 1
|
|
29
41
|
*
|
|
42
|
+
* assert.deepStrictEqual(mut_history, [1]);
|
|
43
|
+
*
|
|
30
44
|
* num$.next(1); // nothing logged
|
|
31
45
|
*
|
|
46
|
+
* assert.deepStrictEqual(mut_history, [1]);
|
|
47
|
+
*
|
|
32
48
|
* num$.next(2); // logs: 2
|
|
49
|
+
*
|
|
50
|
+
* assert.deepStrictEqual(mut_history, [1, 2]);
|
|
51
|
+
*
|
|
52
|
+
* num$.next(2); // nothing logged
|
|
53
|
+
*
|
|
54
|
+
* num$.next(3); // logs: 3
|
|
55
|
+
*
|
|
56
|
+
* assert.deepStrictEqual(mut_history, [1, 2, 3]);
|
|
33
57
|
* ```
|
|
34
58
|
*/
|
|
35
59
|
export const skipIfNoChange = <A,>(
|
|
@@ -43,10 +67,10 @@ export const skipIfNoChange = <A,>(
|
|
|
43
67
|
)) as KeepInitialValueOperator<A, A>;
|
|
44
68
|
|
|
45
69
|
/**
|
|
46
|
-
* Alias for `skipIfNoChange
|
|
70
|
+
* Alias for `skipIfNoChange`.
|
|
47
71
|
* @see skipIfNoChange
|
|
48
72
|
*/
|
|
49
|
-
export const distinctUntilChanged = skipIfNoChange;
|
|
73
|
+
export const distinctUntilChanged = skipIfNoChange;
|
|
50
74
|
|
|
51
75
|
class SkipIfNoChangeObservableClass<A>
|
|
52
76
|
extends SyncChildObservableClass<A, readonly [A]>
|
|
@@ -7,6 +7,56 @@ import {
|
|
|
7
7
|
type UpdaterSymbol,
|
|
8
8
|
} from '../types/index.mjs';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Skips all values from the source observable until the notifier observable emits.
|
|
12
|
+
*
|
|
13
|
+
* @template A - The type of values from the source
|
|
14
|
+
* @param notifier - An observable that signals when to start emitting
|
|
15
|
+
* @returns An operator that skips values until the notifier emits
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* // Timeline:
|
|
20
|
+
* //
|
|
21
|
+
* // num$ 1 2 3 start 4 5 6
|
|
22
|
+
* // startNotifier X
|
|
23
|
+
* // skipped$ 4 5 6
|
|
24
|
+
* // |------ skipped -------|
|
|
25
|
+
* //
|
|
26
|
+
* // Explanation:
|
|
27
|
+
* // - skipUntil ignores all values until the notifier emits
|
|
28
|
+
* // - After the notifier emits, all subsequent values are passed through
|
|
29
|
+
* // - Opposite of takeUntil (which completes when notifier emits)
|
|
30
|
+
*
|
|
31
|
+
* const num$ = source<number>();
|
|
32
|
+
*
|
|
33
|
+
* const [startNotifier, start_] = createEventEmitter();
|
|
34
|
+
*
|
|
35
|
+
* const skipped$ = num$.pipe(skipUntil(startNotifier));
|
|
36
|
+
*
|
|
37
|
+
* const mut_history: number[] = [];
|
|
38
|
+
*
|
|
39
|
+
* skipped$.subscribe((x) => {
|
|
40
|
+
* mut_history.push(x);
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* num$.next(1); // nothing logged
|
|
44
|
+
*
|
|
45
|
+
* num$.next(2); // nothing logged
|
|
46
|
+
*
|
|
47
|
+
* assert.deepStrictEqual(mut_history, []);
|
|
48
|
+
*
|
|
49
|
+
* start_();
|
|
50
|
+
*
|
|
51
|
+
* num$.next(4); // logs: 4
|
|
52
|
+
*
|
|
53
|
+
* assert.deepStrictEqual(mut_history, [4]);
|
|
54
|
+
*
|
|
55
|
+
* num$.next(5); // logs: 5
|
|
56
|
+
*
|
|
57
|
+
* assert.deepStrictEqual(mut_history, [4, 5]);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
10
60
|
export const skipUntil =
|
|
11
61
|
<A,>(notifier: Observable<unknown>): DropInitialValueOperator<A, A> =>
|
|
12
62
|
(parentObservable) =>
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Optional,
|
|
3
|
-
PositiveSafeInt,
|
|
4
|
-
SafeUint,
|
|
5
|
-
asSafeUint,
|
|
6
|
-
pipe,
|
|
7
|
-
} from 'ts-data-forge';
|
|
1
|
+
import { Optional, SafeUint, asSafeUint, pipe } from 'ts-data-forge';
|
|
8
2
|
import { SyncChildObservableClass } from '../class/index.mjs';
|
|
9
3
|
import {
|
|
10
4
|
type DropInitialValueOperator,
|
|
@@ -13,6 +7,54 @@ import {
|
|
|
13
7
|
type UpdaterSymbol,
|
|
14
8
|
} from '../types/index.mjs';
|
|
15
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Skips values from the source observable while the predicate returns true.
|
|
12
|
+
* Once the predicate returns false, all subsequent values pass through.
|
|
13
|
+
*
|
|
14
|
+
* @template A - The type of values from the source
|
|
15
|
+
* @param predicate - Function to test each value
|
|
16
|
+
* @returns An operator that skips values while the predicate is true
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // Timeline:
|
|
21
|
+
* //
|
|
22
|
+
* // num$ 1 2 3 4 5 6 7
|
|
23
|
+
* // skipped$ 5 6 7
|
|
24
|
+
* // |---- skip -----|
|
|
25
|
+
* //
|
|
26
|
+
* // Explanation:
|
|
27
|
+
* // - skipWhile skips values while the predicate returns true
|
|
28
|
+
* // - Once the predicate returns false, all subsequent values pass through
|
|
29
|
+
* // - Unlike filter, the predicate is never checked again after the first false
|
|
30
|
+
*
|
|
31
|
+
* const num$ = source<number>();
|
|
32
|
+
*
|
|
33
|
+
* const skipped$ = num$.pipe(skipWhile((x) => x < 5));
|
|
34
|
+
*
|
|
35
|
+
* const mut_history: number[] = [];
|
|
36
|
+
*
|
|
37
|
+
* skipped$.subscribe((x) => {
|
|
38
|
+
* mut_history.push(x);
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* num$.next(1); // nothing logged
|
|
42
|
+
*
|
|
43
|
+
* num$.next(2); // nothing logged
|
|
44
|
+
*
|
|
45
|
+
* num$.next(5); // logs: 5
|
|
46
|
+
*
|
|
47
|
+
* assert.deepStrictEqual(mut_history, [5]);
|
|
48
|
+
*
|
|
49
|
+
* num$.next(6); // logs: 6
|
|
50
|
+
*
|
|
51
|
+
* assert.deepStrictEqual(mut_history, [5, 6]);
|
|
52
|
+
*
|
|
53
|
+
* num$.next(7); // logs: 7
|
|
54
|
+
*
|
|
55
|
+
* assert.deepStrictEqual(mut_history, [5, 6, 7]);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
16
58
|
export const skipWhile =
|
|
17
59
|
<A,>(
|
|
18
60
|
predicate: (value: A, index: SafeUint | -1) => boolean,
|
|
@@ -20,15 +62,6 @@ export const skipWhile =
|
|
|
20
62
|
(parentObservable) =>
|
|
21
63
|
new SkipWhileObservableClass(parentObservable, predicate);
|
|
22
64
|
|
|
23
|
-
/* Specialized operators */
|
|
24
|
-
|
|
25
|
-
export const skip = <A,>(
|
|
26
|
-
n: PositiveSafeIntWithSmallInt,
|
|
27
|
-
): DropInitialValueOperator<A, A> =>
|
|
28
|
-
!PositiveSafeInt.is(n) ? idFn : skipWhile((_, index) => index + 1 <= n);
|
|
29
|
-
|
|
30
|
-
const idFn = <T,>(value: T): T => value;
|
|
31
|
-
|
|
32
65
|
/* implementation */
|
|
33
66
|
|
|
34
67
|
class SkipWhileObservableClass<A>
|
|
@@ -19,18 +19,52 @@ import {
|
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* ```ts
|
|
22
|
+
* // Timeline:
|
|
23
|
+
* //
|
|
24
|
+
* // searchQuery$ "a" "ab" "abc"
|
|
25
|
+
* // requests fetch1 fetch2 fetch3
|
|
26
|
+
* // results$ cancel cancel result3
|
|
27
|
+
* // fetch1 fetch2
|
|
28
|
+
* //
|
|
29
|
+
* // Explanation:
|
|
30
|
+
* // - switchMap cancels previous inner observables when a new value arrives
|
|
31
|
+
* // - Only the result from the latest search query is emitted
|
|
32
|
+
* // - Previous ongoing requests are cancelled
|
|
33
|
+
* // - Ideal for search-as-you-type scenarios
|
|
34
|
+
*
|
|
22
35
|
* const searchQuery$ = source<string>();
|
|
23
36
|
*
|
|
24
37
|
* const results$ = searchQuery$.pipe(
|
|
25
|
-
* switchMap((query) =>
|
|
38
|
+
* switchMap((query) => {
|
|
39
|
+
* const result$ = source<string[]>();
|
|
40
|
+
*
|
|
41
|
+
* setTimeout(() => {
|
|
42
|
+
* result$.next([query]);
|
|
43
|
+
*
|
|
44
|
+
* result$.complete();
|
|
45
|
+
* }, 10);
|
|
46
|
+
*
|
|
47
|
+
* return result$;
|
|
48
|
+
* }),
|
|
26
49
|
* );
|
|
27
50
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
51
|
+
* const mut_history: string[][] = [];
|
|
52
|
+
*
|
|
53
|
+
* results$.subscribe((value) => {
|
|
54
|
+
* mut_history.push(value);
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* searchQuery$.next('a');
|
|
58
|
+
*
|
|
59
|
+
* searchQuery$.next('ab');
|
|
60
|
+
*
|
|
61
|
+
* searchQuery$.next('abc');
|
|
62
|
+
*
|
|
63
|
+
* await new Promise((resolve) => {
|
|
64
|
+
* setTimeout(resolve, 200);
|
|
30
65
|
* });
|
|
31
|
-
* // Only the latest search results are emitted, previous searches are cancelled
|
|
32
66
|
*
|
|
33
|
-
*
|
|
67
|
+
* assert.deepStrictEqual(mut_history, [['abc']]);
|
|
34
68
|
* ```
|
|
35
69
|
*
|
|
36
70
|
* @note To improve code readability, consider using `createState` instead of `switchMap`,
|