Reputation: 4456
When I subscribe to a shared mapping from BehaviorSubject
instance (t
), only first subscription is executed.
When the original BehaviorSubject
(obj
) emits second value, only the latest value is printed, and both subscriptions were executed.
Let check my code
const obj = new Rx.BehaviorSubject(1)
obj.subscribe(console.log)
const t = obj.map(u => {
console.log("mapped")
return u * 10
}).share()
t.subscribe(x => console.log("subscribe 1 " + x))
t.subscribe(x => console.log("subscribe 2 " + x))
//with the following line un-commented, both subscriptions print out new value
//obj.next(2)
My expected result is
1
mapped
subscribe 1 10
subscribe 2 10
but the actual result was
1
mapped
subscribe 1 10
Sorry for the naive question. Is there anyone can explain this to me?
Thank you so much
Upvotes: 1
Views: 406
Reputation: 96899
In your example you have two Subjects:
the BehaviorSubject
in obj
.
Subject
instance inside .share()
.
Remember that BehaviorSubject
emits its cached value only when you subscribe to it.
The first observer obj.subscribe(console.log)
subscribes directly to the BehaviorSubject
. This prints 1
.
Then you create a chain t
that ends with the share()
operator.
Now you subscribe to t
with t.subscribe
. This means you subscribe to the Subject
inside share()
and since this is its first observer it needs to subscribe to its source Observable (which in turn reaches the source BehaviorSubject
that emits its cached value). Note that share()
is just a shortcut for using the multicast()
operator with refCount()
.
And the last line you subscribe again with t.subscribe
. Just like previously this subscribes to the Subject
inside share()
. However share()
already is subscribed to its source Observable so it doesn't make another subscription. That's the point of multicasting and the multicast()
operator.
That's why you won't see any subscribe 2 10
and you won't event see mapped
printed twice. You're subscribing to the Subject
inside share()
, not the source BehaviorSubject
.
Upvotes: 0
Reputation: 16892
Any operator (including the share
) actually creates a new Sub-Observable, which has it's own share/replay-properties that are detached from the source-observable.
So to have your result, you should use publishReplay(1)
instead of share()
.
(With publishReplay
you of course have to either use refCount()
or connect()
)
const obj = new Rx.BehaviorSubject(1)
obj.subscribe(console.log)
const t = obj.map(u => {
console.log("mapped")
return u * 10
}).publishReplay(1)
.refCount();
t.subscribe(x => console.log("subscribe 1 " + x))
t.subscribe(x => console.log("subscribe 2 " + x))
//with the following line un-commented, both subscriptions print out new value
//obj.next(2)
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>
Upvotes: 1