user1592129
user1592129

Reputation: 493

3 Different Rest APIs to get Data using RXJS

I am trying to implement an httpService where we have 3 Rest API endpoint. If the first API return a success code then I don't want to call the next end point but i case of error i want to try second or third. I have written my code like

import { of, throwError } from 'rxjs'; import { catchError, mergeMap } from 'rxjs/operators';

this.httpService
  .post(`${primary_system}?id=${params.id}`)
  .pipe(
    catchError((primaryError) => {
      if (!!secondary_system) {
        return this.httpService
          .post(`${secondary_system}?id=${params.id}`)
          .pipe(
            catchError((secondaryError) => {
              if (!!tertiary_system) {
                return this.httpService.post(`${tertiary_system}?id=${params.id}`);
              }
              return of(secondaryError);
            })
          );
      }
      return of(primaryError);
    })
  );

certainly the will be a way to flattern these nested calls. I think this is bad practice to pipe Observables like this. Any better solution?

Upvotes: 1

Views: 71

Answers (1)

Picci
Picci

Reputation: 17762

You do not need to embed the second catchError into the closure of the first catchError.

In other words you can do something like this

this.httpService
  .post(`${primary_system}?id=${params.id}`)
  .pipe(
    catchError((primaryError) => {
      if (!!secondary_system) {
        return this.httpService
          .post(`${secondary_system}?id=${params.id}`)
          );
      }
      return of(primaryError);
    }),
    // here you catch an error that is generated by the call to the
    // secondary system
    catchError((secondaryError) => {
      if (!!tertiary_system) {
         return this.httpService.post(`${tertiary_system}?id=${params.id}`);
      }
      return of(secondaryError);
    })
  );

You could also make the code maybe more readable by introducing 2 functions that represent the calls to the secondary and tertiary systems, like this

// this function returns an Observable that represents the call to the
// secondary system if it catches an error coming from upstream
function callSecondIfFirstFail(id: any) {
   return pipe(
      catchError((primaryError) => {
        if (!!secondary_system) {
          return this.httpService.post(`${secondary_system}?id=${id}`));
        }
        return of(primaryError);
      }),
   )
}

// this function returns an Observable that represents the call to the
// tertiary system if it catches an error coming from upstream
function callThirdIfSecondFail(id: any) {
   return pipe(
      catchError((secondaryError) => {
        if (!!tertiary_system) {
          return this.httpService.post(`${tertiary_system}?id=${id}`));
        }
        return of(secondaryError);
      }),
   )
}

// this is then how the code that performs the, possible, three calls
// would look like
this.httpService
  .post(`${primary_system}?id=${params.id}`).pipe(
     callSecondIfFirstFail(params.id),
     callThirdIfSecondFail(params.id)
  )

This stackblitz tries to represent this idea.

Upvotes: 3

Related Questions