@fncts/observable 0.0.25 → 0.0.27
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/Observable/api/raceWith.d.ts +0 -1
- package/Observable/api/repeatWhen.d.ts +1 -1
- package/Observable/api/share.d.ts +1 -1
- package/Observable/api.d.ts +4 -4
- package/Observable/definition.d.ts +1 -4
- package/Observable.d.ts +16 -16
- package/ObservableRef.d.ts +2 -2
- package/Operator.d.ts +3 -3
- package/Subject.d.ts +16 -7
- package/Subscriber.d.ts +23 -8
- package/Subscription.d.ts +2 -2
- package/_cjs/Action.cjs +2 -3
- package/_cjs/Action.cjs.map +1 -1
- package/_cjs/AnimationFrameAction.cjs +3 -3
- package/_cjs/AnimationFrameAction.cjs.map +1 -1
- package/_cjs/AnimationFrameScheduler.cjs +3 -3
- package/_cjs/AnimationFrameScheduler.cjs.map +1 -1
- package/_cjs/AsyncAction.cjs +5 -5
- package/_cjs/AsyncAction.cjs.map +1 -1
- package/_cjs/AsyncScheduler.cjs +3 -5
- package/_cjs/AsyncScheduler.cjs.map +1 -1
- package/_cjs/BehaviorSubject.cjs +3 -3
- package/_cjs/BehaviorSubject.cjs.map +1 -1
- package/_cjs/Notification.cjs.map +1 -1
- package/_cjs/Observable/api/connect.cjs +8 -8
- package/_cjs/Observable/api/connect.cjs.map +1 -1
- package/_cjs/Observable/api/connectable.cjs +5 -5
- package/_cjs/Observable/api/connectable.cjs.map +1 -1
- package/_cjs/Observable/api/fromCallback.cjs +3 -3
- package/_cjs/Observable/api/fromCallback.cjs.map +1 -1
- package/_cjs/Observable/api/fromEvent.cjs +2 -2
- package/_cjs/Observable/api/fromEvent.cjs.map +1 -1
- package/_cjs/Observable/api/index.cjs.map +1 -1
- package/_cjs/Observable/api/race.cjs +5 -5
- package/_cjs/Observable/api/race.cjs.map +1 -1
- package/_cjs/Observable/api/raceWith.cjs +4 -5
- package/_cjs/Observable/api/raceWith.cjs.map +1 -1
- package/_cjs/Observable/api/repeatWhen.cjs +10 -9
- package/_cjs/Observable/api/repeatWhen.cjs.map +1 -1
- package/_cjs/Observable/api/retryWhen.cjs +10 -9
- package/_cjs/Observable/api/retryWhen.cjs.map +1 -1
- package/_cjs/Observable/api/share.cjs +10 -10
- package/_cjs/Observable/api/share.cjs.map +1 -1
- package/_cjs/Observable/api/window.cjs +13 -12
- package/_cjs/Observable/api/window.cjs.map +1 -1
- package/_cjs/Observable/api/windowCount.cjs +13 -11
- package/_cjs/Observable/api/windowCount.cjs.map +1 -1
- package/_cjs/Observable/api/windowTime.cjs +13 -12
- package/_cjs/Observable/api/windowTime.cjs.map +1 -1
- package/_cjs/Observable/api/windowToggle.cjs +27 -25
- package/_cjs/Observable/api/windowToggle.cjs.map +1 -1
- package/_cjs/Observable/api/windowWhen.cjs +18 -16
- package/_cjs/Observable/api/windowWhen.cjs.map +1 -1
- package/_cjs/Observable/api.cjs +328 -317
- package/_cjs/Observable/api.cjs.map +1 -1
- package/_cjs/Observable/definition.cjs +8 -15
- package/_cjs/Observable/definition.cjs.map +1 -1
- package/_cjs/Observable/dom/animationFrames.cjs +4 -4
- package/_cjs/Observable/dom/animationFrames.cjs.map +1 -1
- package/_cjs/Observable/instances.cjs.map +1 -1
- package/_cjs/Observable.cjs +64 -64
- package/_cjs/Observable.cjs.map +1 -1
- package/_cjs/ObservableRef/api.cjs +3 -3
- package/_cjs/ObservableRef/api.cjs.map +1 -1
- package/_cjs/ObservableRef/atomic.cjs +3 -3
- package/_cjs/ObservableRef/atomic.cjs.map +1 -1
- package/_cjs/ObservableRef/definition.cjs +2 -2
- package/_cjs/ObservableRef/definition.cjs.map +1 -1
- package/_cjs/ObservableRef.cjs +8 -8
- package/_cjs/ObservableRef.cjs.map +1 -1
- package/_cjs/Observer.cjs.map +1 -1
- package/_cjs/Operator.cjs +10 -15
- package/_cjs/Operator.cjs.map +1 -1
- package/_cjs/Scheduler.cjs +3 -3
- package/_cjs/Scheduler.cjs.map +1 -1
- package/_cjs/Subject.cjs +70 -44
- package/_cjs/Subject.cjs.map +1 -1
- package/_cjs/Subscriber.cjs +123 -71
- package/_cjs/Subscriber.cjs.map +1 -1
- package/_cjs/Subscription.cjs +8 -8
- package/_cjs/Subscription.cjs.map +1 -1
- package/_cjs/config.cjs +15 -0
- package/_cjs/config.cjs.map +1 -0
- package/_cjs/global.cjs.map +1 -1
- package/_cjs/index.cjs +14 -14
- package/_cjs/index.cjs.map +1 -1
- package/_cjs/internal/animationFrameProvider.cjs +2 -2
- package/_cjs/internal/animationFrameProvider.cjs.map +1 -1
- package/_cjs/internal/args.cjs +2 -2
- package/_cjs/internal/args.cjs.map +1 -1
- package/_cjs/internal/intervalProvider.cjs.map +1 -1
- package/_cjs/internal/performanceTimestampProvider.cjs.map +1 -1
- package/_cjs/internal/timeoutProvider.cjs.map +1 -1
- package/_cjs/internal/timestampProvider.cjs.map +1 -1
- package/_cjs/internal/util.cjs +3 -3
- package/_cjs/internal/util.cjs.map +1 -1
- package/_mjs/Action.mjs +0 -1
- package/_mjs/Action.mjs.map +1 -1
- package/_mjs/AnimationFrameAction.mjs.map +1 -1
- package/_mjs/AnimationFrameScheduler.mjs.map +1 -1
- package/_mjs/AsyncAction.mjs +3 -3
- package/_mjs/AsyncAction.mjs.map +1 -1
- package/_mjs/AsyncScheduler.mjs +0 -2
- package/_mjs/AsyncScheduler.mjs.map +1 -1
- package/_mjs/BehaviorSubject.mjs +1 -1
- package/_mjs/BehaviorSubject.mjs.map +1 -1
- package/_mjs/Notification.mjs.map +1 -1
- package/_mjs/Observable/api/connect.mjs +6 -6
- package/_mjs/Observable/api/connect.mjs.map +1 -1
- package/_mjs/Observable/api/connectable.mjs +1 -1
- package/_mjs/Observable/api/connectable.mjs.map +1 -1
- package/_mjs/Observable/api/fromCallback.mjs.map +1 -1
- package/_mjs/Observable/api/fromEvent.mjs.map +1 -1
- package/_mjs/Observable/api/index.mjs.map +1 -1
- package/_mjs/Observable/api/race.mjs +1 -1
- package/_mjs/Observable/api/race.mjs.map +1 -1
- package/_mjs/Observable/api/raceWith.mjs +3 -4
- package/_mjs/Observable/api/raceWith.mjs.map +1 -1
- package/_mjs/Observable/api/repeatWhen.mjs +9 -8
- package/_mjs/Observable/api/repeatWhen.mjs.map +1 -1
- package/_mjs/Observable/api/retryWhen.mjs +9 -8
- package/_mjs/Observable/api/retryWhen.mjs.map +1 -1
- package/_mjs/Observable/api/share.mjs +8 -8
- package/_mjs/Observable/api/share.mjs.map +1 -1
- package/_mjs/Observable/api/window.mjs +12 -11
- package/_mjs/Observable/api/window.mjs.map +1 -1
- package/_mjs/Observable/api/windowCount.mjs +12 -10
- package/_mjs/Observable/api/windowCount.mjs.map +1 -1
- package/_mjs/Observable/api/windowTime.mjs +11 -10
- package/_mjs/Observable/api/windowTime.mjs.map +1 -1
- package/_mjs/Observable/api/windowToggle.mjs +25 -23
- package/_mjs/Observable/api/windowToggle.mjs.map +1 -1
- package/_mjs/Observable/api/windowWhen.mjs +17 -15
- package/_mjs/Observable/api/windowWhen.mjs.map +1 -1
- package/_mjs/Observable/api.mjs +306 -295
- package/_mjs/Observable/api.mjs.map +1 -1
- package/_mjs/Observable/definition.mjs +2 -9
- package/_mjs/Observable/definition.mjs.map +1 -1
- package/_mjs/Observable/dom/animationFrames.mjs +1 -1
- package/_mjs/Observable/dom/animationFrames.mjs.map +1 -1
- package/_mjs/Observable/instances.mjs.map +1 -1
- package/_mjs/Observable.mjs +16 -19
- package/_mjs/Observable.mjs.map +1 -1
- package/_mjs/ObservableRef/api.mjs.map +1 -1
- package/_mjs/ObservableRef/atomic.mjs.map +1 -1
- package/_mjs/ObservableRef/definition.mjs.map +1 -1
- package/_mjs/ObservableRef.mjs +2 -3
- package/_mjs/ObservableRef.mjs.map +1 -1
- package/_mjs/Observer.mjs.map +1 -1
- package/_mjs/Operator.mjs +6 -11
- package/_mjs/Operator.mjs.map +1 -1
- package/_mjs/Scheduler.mjs.map +1 -1
- package/_mjs/Subject.mjs +65 -39
- package/_mjs/Subject.mjs.map +1 -1
- package/_mjs/Subscriber.mjs +119 -67
- package/_mjs/Subscriber.mjs.map +1 -1
- package/_mjs/Subscription.mjs +6 -6
- package/_mjs/Subscription.mjs.map +1 -1
- package/_mjs/config.mjs +9 -0
- package/_mjs/config.mjs.map +1 -0
- package/_mjs/global.mjs.map +1 -1
- package/_mjs/index.mjs.map +1 -1
- package/_mjs/internal/animationFrameProvider.mjs.map +1 -1
- package/_mjs/internal/args.mjs.map +1 -1
- package/_mjs/internal/intervalProvider.mjs.map +1 -1
- package/_mjs/internal/performanceTimestampProvider.mjs.map +1 -1
- package/_mjs/internal/timeoutProvider.mjs.map +1 -1
- package/_mjs/internal/timestampProvider.mjs.map +1 -1
- package/_mjs/internal/util.mjs.map +1 -1
- package/_src/Action.ts +0 -1
- package/_src/AsyncAction.ts +3 -3
- package/_src/AsyncScheduler.ts +0 -2
- package/_src/BehaviorSubject.ts +1 -1
- package/_src/Observable/api/connect.ts +2 -2
- package/_src/Observable/api/connectable.ts +1 -1
- package/_src/Observable/api/race.ts +1 -1
- package/_src/Observable/api/raceWith.ts +2 -5
- package/_src/Observable/api/repeatWhen.ts +4 -4
- package/_src/Observable/api/retryWhen.ts +3 -3
- package/_src/Observable/api/share.ts +6 -6
- package/_src/Observable/api/window.ts +3 -3
- package/_src/Observable/api/windowCount.ts +30 -33
- package/_src/Observable/api/windowTime.ts +4 -4
- package/_src/Observable/api/windowToggle.ts +19 -21
- package/_src/Observable/api/windowWhen.ts +10 -13
- package/_src/Observable/api.ts +358 -366
- package/_src/Observable/definition.ts +2 -17
- package/_src/Observable/dom/animationFrames.ts +1 -1
- package/_src/Observable.ts +18 -19
- package/_src/ObservableRef.ts +2 -3
- package/_src/Operator.ts +9 -21
- package/_src/Subject.ts +66 -39
- package/_src/Subscriber.ts +134 -59
- package/_src/Subscription.ts +8 -8
- package/_src/config.ts +40 -0
- package/_src/global.ts +1 -1
- package/config.d.ts +36 -0
- package/global.d.ts +1 -1
- package/package.json +2 -2
|
@@ -19,7 +19,6 @@ export class Observable<R, E, A> implements Subscribable<E, A>, AsyncIterable<A>
|
|
|
19
19
|
readonly [ObservableTypeId]: ObservableTypeId = ObservableTypeId;
|
|
20
20
|
|
|
21
21
|
protected source: Observable<any, any, any> | undefined;
|
|
22
|
-
protected operator: Operator<E, A> | undefined;
|
|
23
22
|
protected environment: Environment<any> = Environment();
|
|
24
23
|
|
|
25
24
|
constructor(
|
|
@@ -80,19 +79,11 @@ export class Observable<R, E, A> implements Subscribable<E, A>, AsyncIterable<A>
|
|
|
80
79
|
};
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
lift<R1, E1, A1>(operator: Operator<E1, A1>): Observable<R1, E1, A1> {
|
|
84
|
-
const observable = new Observable<R1, E1, A1>();
|
|
85
|
-
observable.source = this;
|
|
86
|
-
observable.operator = operator;
|
|
87
|
-
return observable;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
82
|
provideEnvironment(environment: Environment<R>): Observable<never, E, A>;
|
|
91
83
|
provideEnvironment<In>(environment: Environment<In>): Observable<Exclude<R, In>, E, A>;
|
|
92
84
|
provideEnvironment<In>(environment: Environment<In>): Observable<Exclude<R, In>, E, A> {
|
|
93
85
|
const observable = new Observable<never, E, A>(this.subscribeInternal);
|
|
94
86
|
observable.source = this.source;
|
|
95
|
-
observable.operator = this.operator;
|
|
96
87
|
observable.environment = this.environment.union(environment);
|
|
97
88
|
return observable;
|
|
98
89
|
}
|
|
@@ -104,15 +95,9 @@ export class Observable<R, E, A> implements Subscribable<E, A>, AsyncIterable<A>
|
|
|
104
95
|
this: Observable<never, E, A>,
|
|
105
96
|
observer?: Partial<Observer<E, A>> | ((value: A) => void),
|
|
106
97
|
): Subscription {
|
|
107
|
-
const subscriber: Subscriber<E, A> = isSubscriber(observer) ? observer : new
|
|
98
|
+
const subscriber: Subscriber<E, A> = isSubscriber(observer) ? observer : new Subscriber(observer);
|
|
108
99
|
|
|
109
|
-
subscriber.add(
|
|
110
|
-
this.operator
|
|
111
|
-
? this.operator.call(subscriber, this.source, this.environment)
|
|
112
|
-
: this.source
|
|
113
|
-
? this.subscribeInternal(subscriber, this.environment)
|
|
114
|
-
: this.trySubscribe(subscriber, this.environment),
|
|
115
|
-
);
|
|
100
|
+
subscriber.add(this.trySubscribe(subscriber, this.environment));
|
|
116
101
|
|
|
117
102
|
return subscriber;
|
|
118
103
|
}
|
|
@@ -31,7 +31,7 @@ function animationFramesInternal(timestampProvider?: TimestampProvider): Observa
|
|
|
31
31
|
timestamp: timestampProvider ? now : timestamp,
|
|
32
32
|
elapsed: now - start,
|
|
33
33
|
});
|
|
34
|
-
if (!subscriber.
|
|
34
|
+
if (!subscriber._closed) {
|
|
35
35
|
subscription.add(schedule(run));
|
|
36
36
|
}
|
|
37
37
|
};
|
package/_src/Observable.ts
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
/* eslint-disable simple-import-sort/exports */
|
|
2
1
|
// codegen:start { preset: barrel, include: Observable/*.ts }
|
|
3
|
-
export * from "./Observable/instances.js";
|
|
4
|
-
export * from "./Observable/definition.js";
|
|
5
2
|
export * from "./Observable/api.js";
|
|
3
|
+
export * from "./Observable/definition.js";
|
|
4
|
+
export * from "./Observable/instances.js";
|
|
6
5
|
// codegen:end
|
|
7
|
-
|
|
6
|
+
|
|
8
7
|
// codegen:start { preset: barrel, include: Observable/api/*.ts }
|
|
9
|
-
export * from "./Observable/api/windowWhen.js";
|
|
10
|
-
export * from "./Observable/api/windowToggle.js";
|
|
11
|
-
export * from "./Observable/api/windowTime.js";
|
|
12
|
-
export * from "./Observable/api/windowCount.js";
|
|
13
|
-
export * from "./Observable/api/window.js";
|
|
14
|
-
export * from "./Observable/api/share.js";
|
|
15
|
-
export * from "./Observable/api/retryWhen.js";
|
|
16
|
-
export * from "./Observable/api/repeatWhen.js";
|
|
17
|
-
export * from "./Observable/api/raceWith.js";
|
|
18
|
-
export * from "./Observable/api/race.js";
|
|
19
|
-
export * from "./Observable/api/index.js";
|
|
20
|
-
export * from "./Observable/api/fromEvent.js";
|
|
21
|
-
export * from "./Observable/api/fromCallback.js";
|
|
22
|
-
export * from "./Observable/api/connectable.js";
|
|
23
8
|
export * from "./Observable/api/connect.js";
|
|
9
|
+
export * from "./Observable/api/connectable.js";
|
|
10
|
+
export * from "./Observable/api/fromCallback.js";
|
|
11
|
+
export * from "./Observable/api/fromEvent.js";
|
|
12
|
+
export * from "./Observable/api/index.js";
|
|
13
|
+
export * from "./Observable/api/race.js";
|
|
14
|
+
export * from "./Observable/api/raceWith.js";
|
|
15
|
+
export * from "./Observable/api/repeatWhen.js";
|
|
16
|
+
export * from "./Observable/api/retryWhen.js";
|
|
17
|
+
export * from "./Observable/api/share.js";
|
|
18
|
+
export * from "./Observable/api/window.js";
|
|
19
|
+
export * from "./Observable/api/windowCount.js";
|
|
20
|
+
export * from "./Observable/api/windowTime.js";
|
|
21
|
+
export * from "./Observable/api/windowToggle.js";
|
|
22
|
+
export * from "./Observable/api/windowWhen.js";
|
|
24
23
|
// codegen:end
|
|
25
|
-
|
|
24
|
+
|
|
26
25
|
// codegen:start { preset: barrel, include: Observable/dom/*.ts }
|
|
27
26
|
export * from "./Observable/dom/animationFrames.js";
|
|
28
27
|
// codegen:end
|
package/_src/ObservableRef.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/* eslint-disable simple-import-sort/exports */
|
|
2
1
|
// codegen:start { preset: barrel, include: ./ObservableRef/*.ts }
|
|
3
|
-
export * from "./ObservableRef/definition.js";
|
|
4
|
-
export * from "./ObservableRef/atomic.js";
|
|
5
2
|
export * from "./ObservableRef/api.js";
|
|
3
|
+
export * from "./ObservableRef/atomic.js";
|
|
4
|
+
export * from "./ObservableRef/definition.js";
|
|
6
5
|
// codegen:end
|
package/_src/Operator.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { SubscriberOverrides } from "./Subscriber.js";
|
|
2
|
+
|
|
1
3
|
export interface Operator<E, A> {
|
|
2
4
|
call(subscriber: Subscriber<E, A>, source: any, environment: Environment<any>): Finalizer;
|
|
3
5
|
}
|
|
@@ -44,7 +46,7 @@ export class OperatorSubscriber<E, A> extends Subscriber<E, A> {
|
|
|
44
46
|
: super.complete;
|
|
45
47
|
}
|
|
46
48
|
unsubscribe() {
|
|
47
|
-
const { closed } = this;
|
|
49
|
+
const { _closed: closed } = this;
|
|
48
50
|
super.unsubscribe();
|
|
49
51
|
!closed && this.onFinalize?.();
|
|
50
52
|
}
|
|
@@ -56,27 +58,13 @@ export function operatorSubscriber<E, A, E1, A1>(
|
|
|
56
58
|
): OperatorSubscriber<E, A> {
|
|
57
59
|
return new OperatorSubscriber(destination, observer, onFinalize);
|
|
58
60
|
}
|
|
61
|
+
|
|
59
62
|
/**
|
|
60
|
-
* @tsplus pipeable fncts.observable.
|
|
63
|
+
* @tsplus pipeable fncts.observable.Subscriber operate
|
|
61
64
|
*/
|
|
62
|
-
export function operate_<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
environment: Environment<R | R1>,
|
|
67
|
-
) => (() => void) | void,
|
|
68
|
-
) {
|
|
69
|
-
return (source: Observable<R, E, A>): Observable<R1, E1, A1> => {
|
|
70
|
-
return source.lift(function (
|
|
71
|
-
this: Subscriber<E1, A1>,
|
|
72
|
-
liftedSource: Observable<R, E, A>,
|
|
73
|
-
environment: Environment<R | R1>,
|
|
74
|
-
) {
|
|
75
|
-
try {
|
|
76
|
-
f(liftedSource, this, environment);
|
|
77
|
-
} catch (err) {
|
|
78
|
-
this.error(Cause.halt(err));
|
|
79
|
-
}
|
|
80
|
-
});
|
|
65
|
+
export function operate_<E1, A1>(config: SubscriberOverrides<E1, A1>) {
|
|
66
|
+
return <E, A>(destination: Subscriber<E, A>): Subscriber<E1, A1> => {
|
|
67
|
+
// @ts-expect-error
|
|
68
|
+
return new Subscriber<E1, A1>(destination, config);
|
|
81
69
|
};
|
|
82
70
|
}
|
package/_src/Subject.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import { arrayRemove } from "@fncts/observable/internal/util";
|
|
2
|
-
|
|
3
1
|
export interface SubjectLike<E, A> extends Observer<E, A>, Subscribable<E, A> {}
|
|
4
2
|
|
|
3
|
+
/**
|
|
4
|
+
* A Subject is a special type of Observable that allows values to be
|
|
5
|
+
* multicasted to many Observers. Subjects are like EventEmitters.
|
|
6
|
+
*
|
|
7
|
+
* Every Subject is an Observable and an Observer. You can subscribe to a
|
|
8
|
+
* Subject, and you can call next to feed values as well as error and complete.
|
|
9
|
+
*/
|
|
5
10
|
export class Subject<R, E, A> extends Observable<R, E, A> implements SubscriptionLike {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
protected
|
|
11
|
+
_closed = false;
|
|
12
|
+
|
|
13
|
+
protected currentObservers = new Map<number, Observer<E, A>>();
|
|
14
|
+
private observersCount = 0;
|
|
15
|
+
private observerSnapshot: Array<Observer<E, A>> | undefined;
|
|
16
|
+
|
|
9
17
|
protected hasError = false;
|
|
10
18
|
protected thrownError: Cause<E> = null!;
|
|
11
19
|
|
|
@@ -13,83 +21,102 @@ export class Subject<R, E, A> extends Observable<R, E, A> implements Subscriptio
|
|
|
13
21
|
super();
|
|
14
22
|
}
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
get closed() {
|
|
25
|
+
return this._closed;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get observers(): Array<Observer<E, A>> {
|
|
29
|
+
return (this.observerSnapshot ??= Array.from(this.currentObservers.values()));
|
|
20
30
|
}
|
|
21
31
|
|
|
22
32
|
next(value: A) {
|
|
23
|
-
this.
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
for (
|
|
27
|
-
|
|
33
|
+
if (!this._closed) {
|
|
34
|
+
const { observers } = this;
|
|
35
|
+
const len = observers.length;
|
|
36
|
+
for (let i = 0; i < len; i++) {
|
|
37
|
+
observers[i].next(value);
|
|
28
38
|
}
|
|
29
39
|
}
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
error(err: Cause<E>) {
|
|
33
|
-
this.
|
|
34
|
-
|
|
35
|
-
this.hasError = this.isStopped = true;
|
|
43
|
+
if (!this._closed) {
|
|
44
|
+
this.hasError = this._closed = true;
|
|
36
45
|
this.thrownError = err;
|
|
37
46
|
const { observers } = this;
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
const len = observers.length;
|
|
48
|
+
for (let i = 0; i < len; i++) {
|
|
49
|
+
observers[i].error(err);
|
|
40
50
|
}
|
|
51
|
+
this.clearObservers();
|
|
41
52
|
}
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
complete() {
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
this.isStopped = true;
|
|
56
|
+
if (!this._closed) {
|
|
57
|
+
this._closed = true;
|
|
48
58
|
const { observers } = this;
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
const len = observers.length;
|
|
60
|
+
for (let i = 0; i < len; i++) {
|
|
61
|
+
observers[i].complete();
|
|
51
62
|
}
|
|
63
|
+
this.clearObservers();
|
|
52
64
|
}
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
unsubscribe() {
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
68
|
+
this._closed = true;
|
|
69
|
+
this.clearObservers();
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
get observed() {
|
|
61
|
-
return this.
|
|
73
|
+
return this.currentObservers.size > 0;
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
protected throwIfClosed() {
|
|
65
|
-
if (this.
|
|
77
|
+
if (this._closed) {
|
|
66
78
|
throw new Error("Object Unsubscribed");
|
|
67
79
|
}
|
|
68
80
|
}
|
|
69
81
|
|
|
82
|
+
protected clearObservers() {
|
|
83
|
+
this.currentObservers.clear();
|
|
84
|
+
this.observerSnapshot = undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
70
87
|
protected trySubscribe(subscriber: Subscriber<E, A>, environment: Environment<R>): Finalizer {
|
|
71
88
|
this.throwIfClosed();
|
|
72
89
|
return super.trySubscribe(subscriber, environment);
|
|
73
90
|
}
|
|
74
91
|
|
|
75
92
|
protected subscribeInternal(subscriber: Subscriber<E, A>): Subscription {
|
|
76
|
-
this.throwIfClosed();
|
|
77
93
|
this.checkFinalizedStatuses(subscriber);
|
|
78
94
|
return this.innerSubscribe(subscriber);
|
|
79
95
|
}
|
|
80
96
|
|
|
81
97
|
protected innerSubscribe(subscriber: Subscriber<E, A>): Subscription {
|
|
82
|
-
const { hasError,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
const { hasError, _closed: closed } = this;
|
|
99
|
+
if (hasError || closed) {
|
|
100
|
+
return Subscription.empty;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const { currentObservers } = this;
|
|
104
|
+
|
|
105
|
+
const observerId = this.observersCount++;
|
|
106
|
+
currentObservers.set(observerId, subscriber);
|
|
107
|
+
this.observerSnapshot = undefined;
|
|
108
|
+
subscriber.add(() => {
|
|
109
|
+
currentObservers.delete(observerId);
|
|
110
|
+
this.observerSnapshot = undefined;
|
|
111
|
+
});
|
|
112
|
+
return subscriber;
|
|
86
113
|
}
|
|
87
114
|
|
|
88
115
|
protected checkFinalizedStatuses(subscriber: Subscriber<any, any>) {
|
|
89
|
-
const { hasError, thrownError,
|
|
116
|
+
const { hasError, thrownError, _closed: closed } = this;
|
|
90
117
|
if (hasError) {
|
|
91
118
|
subscriber.error(thrownError);
|
|
92
|
-
} else if (
|
|
119
|
+
} else if (closed) {
|
|
93
120
|
subscriber.complete();
|
|
94
121
|
}
|
|
95
122
|
}
|
|
@@ -132,10 +159,10 @@ export class AsyncSubject<R, E, A> extends Subject<R, E, A> {
|
|
|
132
159
|
|
|
133
160
|
/** @internal */
|
|
134
161
|
protected checkFinalizedStatuses(subscriber: Subscriber<E, A>) {
|
|
135
|
-
const { hasError, hasValue, value, thrownError,
|
|
162
|
+
const { hasError, hasValue, value, thrownError, _closed: closed, isComplete } = this;
|
|
136
163
|
if (hasError) {
|
|
137
164
|
subscriber.error(thrownError);
|
|
138
|
-
} else if (
|
|
165
|
+
} else if (closed || isComplete) {
|
|
139
166
|
hasValue &&
|
|
140
167
|
value!.match(
|
|
141
168
|
(e) => subscriber.error(e),
|
|
@@ -146,14 +173,14 @@ export class AsyncSubject<R, E, A> extends Subject<R, E, A> {
|
|
|
146
173
|
}
|
|
147
174
|
|
|
148
175
|
next(value: A) {
|
|
149
|
-
if (!this.
|
|
176
|
+
if (!this._closed) {
|
|
150
177
|
this.value = Either.right(value);
|
|
151
178
|
this.hasValue = true;
|
|
152
179
|
}
|
|
153
180
|
}
|
|
154
181
|
|
|
155
182
|
error(err: Cause<E>) {
|
|
156
|
-
if (!this.
|
|
183
|
+
if (!this._closed) {
|
|
157
184
|
this.value = Either.left(err);
|
|
158
185
|
this.hasValue = true;
|
|
159
186
|
}
|
package/_src/Subscriber.ts
CHANGED
|
@@ -1,55 +1,92 @@
|
|
|
1
|
+
import { Cause } from "@fncts/base/data/Cause";
|
|
2
|
+
import { isFunction } from "@fncts/base/util/predicates";
|
|
3
|
+
|
|
4
|
+
import { config } from "./config.js";
|
|
5
|
+
import { reportUnhandledError } from "./internal/util.js";
|
|
6
|
+
import { Notification } from "./Notification.js";
|
|
7
|
+
|
|
1
8
|
export const SubscriberTypeId = Symbol.for("fncts.observable.Subscriber");
|
|
2
9
|
export type SubscriberTypeId = typeof SubscriberTypeId;
|
|
3
10
|
|
|
11
|
+
export interface SubscriberOverrides<E, A> {
|
|
12
|
+
next?: (value: A) => void;
|
|
13
|
+
error?: (error: Cause<E>) => void;
|
|
14
|
+
complete?: () => void;
|
|
15
|
+
finalize?: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @tsplus type fncts.observable.Subscriber
|
|
20
|
+
*/
|
|
4
21
|
export class Subscriber<E, A> extends Subscription implements Observer<E, A> {
|
|
5
22
|
readonly [SubscriberTypeId]: SubscriberTypeId = SubscriberTypeId;
|
|
6
23
|
|
|
7
24
|
private isStopped = false;
|
|
8
|
-
protected
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
protected destination: Subscriber<E, A> | Observer<E, A> | null;
|
|
26
|
+
|
|
27
|
+
protected readonly nextOverride: ((value: A) => void) | null = null;
|
|
28
|
+
protected readonly errorOverride: ((err: Cause<E>) => void) | null = null;
|
|
29
|
+
protected readonly completeOverride: (() => void) | null = null;
|
|
30
|
+
|
|
31
|
+
constructor(
|
|
32
|
+
destination?: Subscriber<E, A> | Partial<Observer<E, A>> | ((value: A) => void) | null,
|
|
33
|
+
overrides?: SubscriberOverrides<E, A>,
|
|
34
|
+
) {
|
|
35
|
+
super(overrides?.finalize);
|
|
36
|
+
|
|
37
|
+
this.destination = destination instanceof Subscriber ? destination : createSafeObserver(destination);
|
|
38
|
+
|
|
39
|
+
this.nextOverride = overrides?.next ?? null;
|
|
40
|
+
this.errorOverride = overrides?.error ?? null;
|
|
41
|
+
this.completeOverride = overrides?.complete ?? null;
|
|
42
|
+
|
|
43
|
+
this.next = this.nextOverride ? overrideNext : this.next;
|
|
44
|
+
this.error = this.errorOverride ? overrideError : this.error;
|
|
45
|
+
this.complete = this.completeOverride ? overrideComplete : this.complete;
|
|
46
|
+
|
|
47
|
+
if (hasAddAndUnsubscribe(destination)) {
|
|
48
|
+
destination.add(this);
|
|
19
49
|
}
|
|
20
50
|
}
|
|
51
|
+
|
|
21
52
|
next(value: A) {
|
|
22
|
-
if (
|
|
53
|
+
if (this.isStopped) {
|
|
54
|
+
handleStoppedNotification(Notification.next(value), this);
|
|
55
|
+
} else {
|
|
23
56
|
this._next(value);
|
|
24
57
|
}
|
|
25
58
|
}
|
|
26
59
|
error(err: Cause<E>) {
|
|
27
|
-
if (
|
|
60
|
+
if (this.isStopped) {
|
|
61
|
+
handleStoppedNotification(Notification.error(err), this);
|
|
62
|
+
} else {
|
|
28
63
|
this.isStopped = true;
|
|
29
64
|
this._error(err);
|
|
30
65
|
}
|
|
31
66
|
}
|
|
32
67
|
complete() {
|
|
33
|
-
if (
|
|
68
|
+
if (this.isStopped) {
|
|
69
|
+
handleStoppedNotification(Notification.complete(), this);
|
|
70
|
+
} else {
|
|
34
71
|
this.isStopped = true;
|
|
35
72
|
this._complete();
|
|
36
73
|
}
|
|
37
74
|
}
|
|
38
75
|
unsubscribe(): void {
|
|
39
|
-
if (!this.
|
|
76
|
+
if (!this._closed) {
|
|
40
77
|
this.isStopped = true;
|
|
41
78
|
super.unsubscribe();
|
|
42
|
-
this.
|
|
79
|
+
this.destination = null;
|
|
43
80
|
}
|
|
44
81
|
}
|
|
45
82
|
|
|
46
83
|
_next(value: A) {
|
|
47
|
-
this.
|
|
84
|
+
this.destination!.next(value);
|
|
48
85
|
}
|
|
49
86
|
|
|
50
87
|
_error(err: Cause<E>) {
|
|
51
88
|
try {
|
|
52
|
-
this.
|
|
89
|
+
this.destination!.error(err);
|
|
53
90
|
} finally {
|
|
54
91
|
this.unsubscribe();
|
|
55
92
|
}
|
|
@@ -57,60 +94,89 @@ export class Subscriber<E, A> extends Subscription implements Observer<E, A> {
|
|
|
57
94
|
|
|
58
95
|
_complete() {
|
|
59
96
|
try {
|
|
60
|
-
this.
|
|
97
|
+
this.destination!.complete();
|
|
61
98
|
} finally {
|
|
62
99
|
this.unsubscribe();
|
|
63
100
|
}
|
|
64
101
|
}
|
|
65
102
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
103
|
+
|
|
104
|
+
function createSafeObserver<E, A>(
|
|
105
|
+
observerOrNext?: Partial<Observer<E, A>> | ((value: A) => void) | null,
|
|
106
|
+
): Observer<E, A> {
|
|
107
|
+
return new ConsumerObserver(
|
|
108
|
+
!observerOrNext || isFunction(observerOrNext) ? { next: observerOrNext ?? undefined } : observerOrNext,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export class ConsumerObserver<E, A> implements Observer<E, A> {
|
|
113
|
+
private onError: (error: Cause<E>) => void = reportUnhandledError;
|
|
114
|
+
constructor(private partialObserver: Partial<Observer<E, A>>) {
|
|
115
|
+
this.onError = partialObserver.error ?? reportUnhandledError;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
next(value: A): void {
|
|
119
|
+
const { partialObserver } = this;
|
|
120
|
+
if (partialObserver.next) {
|
|
121
|
+
try {
|
|
122
|
+
partialObserver.next(value);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
this.onError(Cause.halt(error));
|
|
125
|
+
}
|
|
79
126
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
error(err: Cause<E>): void {
|
|
130
|
+
const { partialObserver } = this;
|
|
131
|
+
if (partialObserver.error) {
|
|
132
|
+
try {
|
|
133
|
+
partialObserver.error(err);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
this.onError(Cause.halt(error));
|
|
136
|
+
}
|
|
86
137
|
} else {
|
|
87
|
-
this.
|
|
88
|
-
next: next ? wrapThrowHandler(next) : noop,
|
|
89
|
-
error: wrapThrowHandler(error ?? defaultErrorHandler),
|
|
90
|
-
complete: complete ? wrapThrowHandler(complete) : noop,
|
|
91
|
-
};
|
|
138
|
+
this.onError(err);
|
|
92
139
|
}
|
|
93
140
|
}
|
|
94
|
-
}
|
|
95
141
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
142
|
+
complete(): void {
|
|
143
|
+
const { partialObserver } = this;
|
|
144
|
+
if (partialObserver.complete) {
|
|
145
|
+
try {
|
|
146
|
+
partialObserver.complete();
|
|
147
|
+
} catch (error) {
|
|
148
|
+
this.onError(Cause.halt(error));
|
|
149
|
+
}
|
|
102
150
|
}
|
|
103
|
-
}
|
|
151
|
+
}
|
|
104
152
|
}
|
|
105
153
|
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
154
|
+
function overrideNext<E, A>(this: Subscriber<E, A>, value: A): void {
|
|
155
|
+
try {
|
|
156
|
+
this.nextOverride!(value);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
this.destination!.error(Cause.halt(error));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function overrideError<E, A>(this: Subscriber<E, A>, err: Cause<E>): void {
|
|
163
|
+
try {
|
|
164
|
+
this.errorOverride!(err);
|
|
165
|
+
} catch (error) {
|
|
166
|
+
this.destination!.error(Cause.halt(error));
|
|
167
|
+
} finally {
|
|
168
|
+
this.unsubscribe();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function overrideComplete<E, A>(this: Subscriber<E, A>): void {
|
|
173
|
+
try {
|
|
174
|
+
this.completeOverride!();
|
|
175
|
+
} catch (error) {
|
|
176
|
+
this.destination!.error(Cause.halt(error));
|
|
177
|
+
} finally {
|
|
178
|
+
this.unsubscribe();
|
|
179
|
+
}
|
|
114
180
|
}
|
|
115
181
|
|
|
116
182
|
function defaultErrorHandler(error: any) {
|
|
@@ -126,6 +192,15 @@ export const EMPTY_OBSERVER: Readonly<Observer<any, any>> & {
|
|
|
126
192
|
complete: noop,
|
|
127
193
|
};
|
|
128
194
|
|
|
195
|
+
function hasAddAndUnsubscribe(value: any): value is Subscription {
|
|
196
|
+
return value && isFunction(value.unsubscribe) && isFunction(value.add);
|
|
197
|
+
}
|
|
198
|
+
|
|
129
199
|
export function isSubscriber(u: unknown): u is Subscriber<any, any> {
|
|
130
200
|
return isObject(u) && SubscriberTypeId in u;
|
|
131
201
|
}
|
|
202
|
+
|
|
203
|
+
function handleStoppedNotification<E, A>(notification: Notification<E, A>, subscriber: Subscriber<E, A>) {
|
|
204
|
+
const { onStoppedNotification } = config;
|
|
205
|
+
onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));
|
|
206
|
+
}
|
package/_src/Subscription.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface Unsubscribable {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export interface SubscriptionLike extends Unsubscribable {
|
|
6
|
-
readonly
|
|
6
|
+
readonly _closed: boolean;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export type Finalizer = Unsubscribable | (() => void) | void;
|
|
@@ -18,7 +18,7 @@ export type SubscriptionTypeId = typeof SubscriptionTypeId;
|
|
|
18
18
|
export class Subscription implements SubscriptionLike {
|
|
19
19
|
readonly [SubscriptionTypeId]: SubscriptionTypeId = SubscriptionTypeId;
|
|
20
20
|
|
|
21
|
-
public
|
|
21
|
+
public _closed = false;
|
|
22
22
|
private finalizers: Set<Finalizer> | null = null;
|
|
23
23
|
private parents: Set<Subscription> | null = null;
|
|
24
24
|
|
|
@@ -27,8 +27,8 @@ export class Subscription implements SubscriptionLike {
|
|
|
27
27
|
unsubscribe(): void {
|
|
28
28
|
let errors: unknown[] | undefined;
|
|
29
29
|
|
|
30
|
-
if (!this.
|
|
31
|
-
this.
|
|
30
|
+
if (!this._closed) {
|
|
31
|
+
this._closed = true;
|
|
32
32
|
|
|
33
33
|
const { parents, initialFinalizer, finalizers } = this;
|
|
34
34
|
|
|
@@ -71,11 +71,11 @@ export class Subscription implements SubscriptionLike {
|
|
|
71
71
|
|
|
72
72
|
add(finalizer: Finalizer): void {
|
|
73
73
|
if (finalizer && finalizer !== this) {
|
|
74
|
-
if (this.
|
|
74
|
+
if (this._closed) {
|
|
75
75
|
executeFinalizer(finalizer);
|
|
76
76
|
} else {
|
|
77
77
|
if (isSubscription(finalizer)) {
|
|
78
|
-
if (finalizer.
|
|
78
|
+
if (finalizer._closed || finalizer.hasParent(this)) {
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
81
|
finalizer.addParent(this);
|
|
@@ -125,8 +125,8 @@ function executeFinalizer(finalizer: Finalizer): void {
|
|
|
125
125
|
* @tsplus static fncts.observable.SubscriptionOps empty
|
|
126
126
|
*/
|
|
127
127
|
export const EMPTY_SUBSCRIPTION = (() => {
|
|
128
|
-
const empty
|
|
129
|
-
empty.
|
|
128
|
+
const empty = new Subscription();
|
|
129
|
+
empty._closed = true;
|
|
130
130
|
return empty;
|
|
131
131
|
})();
|
|
132
132
|
|