简体   繁体   中英

RxJs Observable completes multiple times

Below is a short code snippet of reactive code ( RxJs )

 let subj = new Rx.Subject(); let chain = subj .switchMap(v => Rx.Observable.of(10*v).do(vv => console.log("Switch map", vv))) .share() .take(1); function subscribe(){ chain.subscribe(v => console.log("Next", v), err => console.log("Error",err), () => console.log("Completed")); chain.subscribe(v => console.log("Next2", v), err => console.log("Error2",err), () => console.log("Completed2")); subj.next(Math.random()); } subscribe(); subscribe(); subscribe(); 
 <script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script> 

According to the documentation chain is an Observable which should print the emitted value * 10 ( switchMap ), while printing it only once, no matter what's the number of subscriptions it has ( share ), do it only for the first emitted value and then complete.

The first two bullets work fine, but the last one does not. Here is the output I get:

Switch map 9.022491050934722
Next 9.022491050934722
Completed
Next2 9.022491050934722
Completed2
Switch map 9.172999425126836
Next 9.172999425126836
Completed
Next2 9.172999425126836
Completed2
Switch map 6.168790337405257
Next 6.168790337405257
Completed
Next2 6.168790337405257
Completed2

As you can see, chain is getting completed multiple times.
What makes it possible to complete the same Observable multiple times?

share is a shortcut for the combination of publish and refCount , this means that the stream is only "hot" as long as there is at least 1 subscriber, so after the stream completes, all active subscribers are automatically unsubscribed, which in turn resets the stream, since there are then 0 subscribers. Also: You should put the take(1) before the share since any following operation affects the hot-state.

How to make the stream "truely" shared/hot, independed from any subscribers: Use publish and connect the stream:

 let subj = new Rx.Subject(); let chain = subj .switchMap(v => Rx.Observable.of(10*v).do(vv => console.log("Switch map", vv))) .take(1) .publish(); chain.connect(); function subscribe(){ chain.subscribe(v => console.log("Next", v), err => console.log("Error",err), () => console.log("Completed")); chain.subscribe(v => console.log("Next2", v), err => console.log("Error2",err), () => console.log("Completed2")); subj.next(Math.random()); } subscribe(); subscribe(); subscribe(); 
 <script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM