What's the way to simplify something like the following code example? I can't find the right operator.. could anyone give a short example?
this.returnsObservable1(...)
.subscribe(
success => {
this.returnsObservable2(...)
.subscribe(
success => {
this.returnsObservable3(...)
.subscribe(
success => {
...
},
Nested subscriptions in use A very common use case is to request a data object from our API to then use some of its properties to request a few more related entities. Finally, we combine the received objects to fill our view. In Angular we could implement it like this: this.
To avoid nested subscribe calls you can always map back from a meta branch, such as a stream that has been forked from the main branch through some AJAX call or some other async operation, to a trunk branch by using mergeMap .
The FlatMap operator transforms an Observable by applying a function that you specify to each item emitted by the source Observable, where that function returns an Observable that itself emits items. FlatMap then merges the emissions of these resulting Observables, emitting these merged results as its own sequence.
As mentioned in comments, you are looking for the flatMap
operator.
You can find more details in previous answers :
Your example would read as :
this.returnsObservable1(...) .flatMap(success => this.returnsObservable2(...)) .flatMap(success => this.returnsObservable3(...)) .subscribe(success => {(...)});
Previously answered for RxJS 5, I ended up on this page whilst using 6.
In the case you're on 6 as well (and I think you should be by now) you can use flatmap
as an operator within pipe
.
Modified the example code of @user3743222:
this.returnsObservable1(...) .pipe( flatMap(success => this.returnsObservable2(...)), flatMap(success => this.returnsObservable3(...)) ) .subscribe(success => {(...)});
The switchMap operator can also be useful. Some examples which describe the usefulness of switchMap compared to nested subscriptions can be found here:
This codepen gives a demo: https://codepen.io/anon/pen/zdXBvP?editors=1111
Rx.Observable
.interval(5000)
.subscribe((val) => {
console.log("outer:", val);
Rx.Observable
.interval(1000)
.subscribe((ival) => {
console.log("inner:", val, ival);
});
});
This codepen gives a demo: https://codepen.io/anon/pen/xLeOZW?editors=1111
Rx.Observable
.interval(5000)
.switchMap((val) => {
console.log("outer:", val);
return Rx.Observable.interval(1000).map((ival) => [val, ival]);
})
.subscribe((val) => {
console.log("inner:", val[0], val[1]);
});
You basically need sequencing.
With RxJS concat
, you can just do this:
import { concat } from 'rxjs';
...
concat(
this.returnsObservable1(...),
this.returnsObservable2(...),
this.returnsObservable3(...),
...
)
.subscribe(success => {(...)});
If your subsequent observables need to know the values from the previous ones, you could use the RxJS concatMap
operator.
import { concatMap } from 'rxjs/operators';
...
this.returnsObservable1(...)
.pipe(
concatMap(result1 => this.returnsObservable2(...)),
concatMap(result2 => this.returnsObservable3(...)),
...
)
.subscribe(success => {(...)});
concat: https://www.learnrxjs.io/learn-rxjs/operators/combination/concat
concatMap: https://www.learnrxjs.io/learn-rxjs/operators/transformation/concatmap
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With