0

I have multiple REST-requests to do. The requests should happen in the declared order - one after the end of the other.

At the end of all of them I need to do an action.

How can I get that? I think there must be better way than cascading the requests. But I am pretty bad in RxJS and asynchronous programming.

this.http.get <any> ("/a").subscribe ((resp) => { foo ();  
     this.http.get <any> ("/b").subscribe ((resp) => { bar ();
          this.http.get <any> ("/c").subscribe ((resp) => { baz (); }}}
);

// action now
chris01
  • 10,921
  • 9
  • 54
  • 93
  • 1
    https://stackoverflow.com/questions/42888604/rxjs-observables-nested-subscriptions - generally, nested subscribe calls in RxJS are considered an anti-pattern – Clashsoft Feb 21 '21 at 21:45

2 Answers2

2

What I would use in this case is concatMap.

The code would look something like this

this.http.get <any> ("/a").pipe(
  concatMap(respA => {
    foo();
    return this.http.get <any> ("/b");
  }),
  concatMap(respB => {
    bar();
    return this.http.get <any> ("/c");
  })
).subscribe(
  respC => { 
    baz(); 
  }
);

concatMap ensures that the execution of the calls occurs in sequence.

You may find inspiration on how to use rxJs in frequent http related use cases in this article.

Picci
  • 16,775
  • 13
  • 70
  • 113
1

Use forkJoin for this

import { forkJoin } from 'rxjs';

and use it like this

forkJoin([this.http.get("/a"), this.http.get("/b"), this.http.get("/c")]).subscribe(([respA, respB, respC]) => {});

the input for the forkJoin function has to be an array of observables.

EDIT:

after reading the fair point from @Picci I would suggest using concat operator. You can put side effects into the tap operator of each observable and still pass an array of observables to concat which will maintain sequential order.

const a$ = this.http.get("/a").pipe(tap(() => foo()));
const b$ = this.http.get("/b").pipe(tap(() => bar()));
const c$ = this.http.get("/c").pipe(tap(() => baz()));

concat([a$, b$, c$]).subscribe(([respA, respB, respC]) => {});

// if you want to handle http errors, you can do it like this

const a$ = this.http.get("/a").pipe(
  tap(() => foo()),
  catchError((err) => {
    handleErr(err);
    return of(EMPTY);
  })
);
Lukasz Gawrys
  • 1,234
  • 2
  • 8