-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
In the switch() operator, you'll find this code used to add
subscriptions to the Subscriptions._subscriptions[] array:
this.add(this.innerSubscription = subscribeToResult(this, value));
And you'll find this code to remove them:
const innerSubscription = this.innerSubscription;
if (innerSubscription) {
innerSubscription.unsubscribe();
this.remove(innerSubscription);
}
But note behavior of Subscription.add(s) is not "add s to the array and return s";
behavior is "create a new ChildSubscription from s, add the ChildSubscription to the array,
and return the ChildSubscription."
The consequence? The remove() does not match the add(). The remove() becomes a silent no-op.
The unsubscribe() was successful (good - we get correct program behavior)
but the remove() fails (bad - cannot GC these silent ChildSubscriptions).
RxJS version:
v5.1.0
Code to reproduce:
var parentTicker = Rx.Observable.interval(1000);
var childTickers = parentTicker.map((x) => {
return Rx.Observable.interval(100).take(2);
});
var switcher = childTickers.switch();
var sub = switcher.subscribe(function(x){
console.log('tick #' + x + ': subscriptions = ' +
sub._subscriptions[0]._innerSub._subscriptions.length);
});
http://jsbin.com/zotobo/edit?js,console
Additional information:
PRs with specs and fixes for two operators (switch(), throttle())
will follow this message. Take a look and tell me if you agree
that this is a legit problem and not failed understanding on my part.
( Because if you do agree, this problem also exists in many
operators. Operators audit(), switchMap(), switchMapTo(), windowToggle(),
windowWhen() can be fixed as above, but fixing MergeMap() e.g., is going to
require stepping back and deciding if remove() responsibility should
even live in the operators, or if it should live in the Subscription class
or ChildSubscription class rolled into the unsubscribe methods. )