Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS Observables nested subscriptions?

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 => {
                   ...
                },
like image 283
Max Solid Avatar asked Mar 19 '17 15:03

Max Solid


People also ask

What is nested subscription?

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.

How do I stop nested observables?

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 .

What is FlatMap in RxJS?

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.


4 Answers

As mentioned in comments, you are looking for the flatMap operator.

You can find more details in previous answers :

  • How to do the chain sequence in rxjs
  • Why do we need to use flatMap?

Your example would read as :

this.returnsObservable1(...)   .flatMap(success => this.returnsObservable2(...))   .flatMap(success => this.returnsObservable3(...))   .subscribe(success => {(...)});  
like image 115
user3743222 Avatar answered Sep 20 '22 08:09

user3743222


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 => {(...)});  
like image 41
Mathijs Segers Avatar answered Sep 19 '22 08:09

Mathijs Segers


The switchMap operator can also be useful. Some examples which describe the usefulness of switchMap compared to nested subscriptions can be found here:

  1. situation with nested subscriptions

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); 
      });
  });
  1. situation with switchMap

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]);
  });
like image 20
sdec Avatar answered Sep 18 '22 08:09

sdec


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

like image 42
Ε Г И І И О Avatar answered Sep 21 '22 08:09

Ε Г И І И О