-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Why shareReplay() subscribes to source observable twice? #763
Comments
The problem is that If you look at the source of refCount you'll see that once the count dips to zero, the subscription disconnects, and once it goes up to one again, it reconnects. In All this is a roundabout way of saying don't use @mattpodwysocki is refCount supposed to restart like that? I never noticed it before. |
@paulpdaniels, thanks for your feedback, but why the "Side effect job123" is only printed once? If the source observable is reconnected to, then this message should be printed twice, shouldn't it? |
@paulpdaniels, I also followed you suggestion to use replay()/connect() instead of shareReplay(). The resulted code is shown below and it indeed works. However, there is still one thing confusing me. var Rx = require('rx');
var createJob = function() {
return Rx.Observable.create(function(subscriber) {
console.log("subscribed to create job");
var resolve = function() {
console.log("resolve createJob");
subscriber.onNext("job123");
return subscriber.onCompleted();
};
return setTimeout(resolve, 10);
});
};
var createJobEvtObservable = createJob()
.doOnNext(function(data) {
return console.log("Side effect " + data);
})
.replay();
var doJob = function(jobId) {
console.log("start job " + jobId);
return Rx.Observable.interval(300).take(3).map(function(i) {
return "completed step " + i;
});
};
var doJobEvtObservable = createJobEvtObservable.flatMap(doJob);
createJobEvtObservable.concat(doJobEvtObservable).subscribe(function(evt) {
return console.log("evt=", evt);
});
createJobEvtObservable.connect(); The code above will output
However, if I remove the last line, the one with the connect() call, from my code, nothing will be output. On the contrary, the example showed in https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/replay.md does NOT have any connect() call at all, but it still works. What confused me is why the connect() call is necessary in my code but not in the example code in replay.md? |
You certainly have found the perfect storm of issues :) . You are right it should be printing twice, but it looks like there is a bug in the perf/tap implementation. 'doOnNext' implicitly creates an 'anonymousobserver', when the observable completes the first time, it stops receiving messages. Until I can push a fix, the solution is to use 'tap' with a non-completing observer. That will override the default behavior of creating a new observer. |
@paulpdaniels yes, |
@xwk yes, the overload that takes a selector will auto connect the observable for you, hence why no need for any connect. |
@xwk that indeed was a bug which is now fixed. |
Fix catch operator to not have anymore a shared underlying Subscription, and instead reset the subscription for each new observable replacing the caught error. This fixes a potential memory leak if catch is used as an infinite retry, because subscriptions would be retained since the beginning, and would increasing each time a catch is performed. Resolves issue Reactive-Extensions#763.
Hi,
First, the problem is different from another issue with shareReplay() I mentioned in #758, and I tested the code below with Rx version 2.5.3.
I was expecting the createJob observable, as shown in the code below, should only be subscribed once, since I made it a shared one by doing .shareReplay(). However, it actually was subscribed twice.
The output is as below
You can see 'subscribed to create job' is printed twice, despite of shareReplay(). However, more strangely, the "Side effect job123" indeed only is printed once.
The text was updated successfully, but these errors were encountered: