Reputation: 5988
So I wanted to setup an stream that will only get data when it is subscribed to. If there are multiple subscriptions then I want it to multi-cast to avoid excessive api calls and to cache the last known good so that future subscribers will get the data without having to hit the api. While someone is subscribed I'd like for the data to be refreshed on an interval.
I tried to do all of this with the shareReplay(n)
operator. It does everything I want except that it doesn't unsubscribe from the timer when everyone unsubscribes from it (refCount === 0
). See example below:
const subscription = Rx.Observable.timer(0, 1000)
.do((x) => { console.log('timer 1', x); })
.switchMap(() => {
console.log('call the api');
return Rx.Observable.of('my api call');
})
.shareReplay(1)
.do((x) => { console.log('timer 2'); })
.subscribe(
(x) => { console.log('data', x); }
);
setTimeout(() => {
console.log('unsubscribe');
subscription.unsubscribe();
}, 2500);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.7/Rx.min.js"></script>
The reason seems to be that it additionally waits for the inner observable to complete:
Is there a better operator (or sequence of operators) to use to accomplish this? I'd rather avoid recreating the shareReplay
operator just to remove that condition.
Upvotes: 0
Views: 332
Reputation: 5988
Figured out right after posting this that publishReplay(1).refCount()
does what I described. I am leaving this question around for anyone else that runs into that gotcha.
So publishReplay(1).refCount()
is not the same thing as shareReplay()
. It looks like it was from 5.4.0 till 5.5.0-beta4. Apparently that was a bug and here is the related pr: https://github.com/ReactiveX/rxjs/pull/2910
And I'm not the only confused soul: https://github.com/ReactiveX/rxjs/issues/3034
Upvotes: 1