Skip to content

Commit 0cb21e6

Browse files
Andre Medeirosbenlesh
authored andcommitted
fix(windowToggle): fix window closing and unsubscription semantics
Fix windowToggle in order to unsubscribe inner windows whenever the outer Observable is unsubscribed. Also allow windows to be closed when the closingNotifier Observables complete without having emitted a 'next' value previously. Also only open a new window if the closingSelector hasn't thrown an error.
1 parent 19cc264 commit 0cb21e6

File tree

1 file changed

+31
-25
lines changed

1 file changed

+31
-25
lines changed

src/operators/windowToggle.ts

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ class WindowToggleOperator<T, R, O> implements Operator<T, R> {
2727
}
2828
}
2929

30+
interface WindowContext<T> {
31+
window: Subject<T>;
32+
subscription: Subscription<T>;
33+
}
34+
3035
class WindowToggleSubscriber<T, O> extends Subscriber<T> {
31-
private windows: Subject<T>[] = [];
36+
private contexts: Array<WindowContext<T>> = [];
3237
private closingNotification: Subscription<any>;
3338

3439
constructor(destination: Subscriber<T>,
@@ -39,55 +44,56 @@ class WindowToggleSubscriber<T, O> extends Subscriber<T> {
3944
}
4045

4146
_next(value: T) {
42-
const windows = this.windows;
43-
const len = windows.length;
47+
const contexts = this.contexts;
48+
const len = contexts.length;
4449
for (let i = 0; i < len; i++) {
45-
windows[i].next(value);
50+
contexts[i].window.next(value);
4651
}
4752
}
4853

4954
_error(err: any) {
50-
const windows = this.windows;
51-
while (windows.length > 0) {
52-
windows.shift().error(err);
55+
const contexts = this.contexts;
56+
while (contexts.length > 0) {
57+
contexts.shift().window.error(err);
5358
}
5459
this.destination.error(err);
5560
}
5661

5762
_complete() {
58-
const windows = this.windows;
59-
while (windows.length > 0) {
60-
windows.shift().complete();
63+
const contexts = this.contexts;
64+
while (contexts.length > 0) {
65+
const context = contexts.shift();
66+
context.window.complete();
67+
context.subscription.unsubscribe();
6168
}
6269
this.destination.complete();
6370
}
6471

6572
openWindow(value: O) {
66-
const window = new Subject<T>();
67-
this.windows.push(window);
68-
this.destination.next(window);
69-
let windowContext = {
70-
window,
71-
subscription: new Subscription()
72-
};
73-
7473
const closingSelector = this.closingSelector;
7574
let closingNotifier = tryCatch(closingSelector)(value);
7675
if (closingNotifier === errorObject) {
7776
this.error(closingNotifier.e);
7877
} else {
79-
const subscriber = new WindowClosingNotifierSubscriber<T, O>(this, windowContext);
78+
let context = {
79+
window: new Subject<T>(),
80+
subscription: new Subscription()
81+
};
82+
this.contexts.push(context);
83+
this.destination.next(context.window);
84+
const subscriber = new WindowClosingNotifierSubscriber<T, O>(this, context);
8085
const subscription = closingNotifier._subscribe(subscriber);
81-
this.add(windowContext.subscription.add(subscription));
86+
this.add(context.subscription.add(subscription));
8287
}
8388
}
8489

85-
closeWindow(windowContext: { subscription: Subscription<T>, window: Subject<T> }) {
86-
const { window, subscription } = windowContext;
87-
const windows = this.windows;
88-
windows.splice(windows.indexOf(window), 1);
90+
closeWindow(context: WindowContext<T>) {
91+
const { window, subscription } = context;
92+
const contexts = this.contexts;
93+
contexts.splice(contexts.indexOf(context), 1);
8994
window.complete();
9095
this.remove(subscription);
96+
subscription.unsubscribe();
9197
}
9298
}
9399

@@ -106,7 +112,7 @@ class WindowClosingNotifierSubscriber<T, O> extends Subscriber<T> {
106112
}
107113

108114
_complete() {
109-
// noop
115+
this.parent.closeWindow(this.windowContext);
110116
}
111117
}
112118

0 commit comments

Comments
 (0)