Black Flag Racing
Black Flag Racing

Reputation: 40

How to call an Observable based on outcome of another Observable and return an Observable

Angular 10, creating a service method that returns Observable (User is a custom object I created). I wish to add (an observable) service method that would tell me if the service is up and running, and if not, I'd like to return a different Observable, this one loaded from a local resource.

Pseudo code:

if(serviceRunning()){
  return getUserFromService();
}else{
 return getUserFromLocalResource();
}

My actual methods (these all reside in my UserService module and are being called from my controller methods):

serviceRunning() {
  // Calls service method serviceRunning which returns boolean.
  return this.http.get<boolean>(this.nodeUserSvcUrl + 'api/serviceRunning');
}

getUser(name: string): Observable<User> {
  if (this.serviceRunning()) { // Pseudo code...this line obviously does not work
    // Return user data from service
    return this.http.get<User>(this.nodeUserSvcUrl + 'api/users/' + name);
  } else {
    // Return data from local resource
    return this.getStaticUser(); 
  }
}

// Get local user data
getStaticUser() {
  return this.http.get<User>(this.usersUrl + 'users.json');
}

I have tried a myriad of mergeMap, forkJoin, concatMap code, but nothing worked. The closest solution is similar to this: (Angular4 how to chain forkJoin with flatMap), but he's not returning an Observable - I need to. Therefore I feel like I can't subscribe to the forkJoin/concatMap result as in his code.

Any help would be appreciated!

Update: Per Sivakumar's response below, here's my actual implementation, for those who might need it:

getUser() {
  return this.serviceRunning().pipe(
    switchMap(val => {
      var tmp: Observable<User>;
      val ? 
        tmp = this.http.get<User>(this.nodeUserSvcUrl + 'api/users/' + name)
      :
        tmp = this.getStaticUser();
      return tmp;
    })
  );
}

Upvotes: 1

Views: 2833

Answers (1)

Sivakumar Tadisetti
Sivakumar Tadisetti

Reputation: 5051

You can use switchMap for this scenario

Working Stackblitz

import { Injectable } from "@angular/core";
import { of } from "rxjs";
import { switchMap } from "rxjs/operators";

@Injectable({
  providedIn: "root"
})
export class TestService {
  test: boolean = true;

  serviceRunning() {
    return of(this.test).pipe(
      switchMap(val =>
        val ? this.getUserFromRemote() : this.getUserFromLocal()
      )
    );
  }

  getUserFromRemote() {
    return of("User from Remote");
  }

  getUserFromLocal() {
    return of("User from Local");
  }
}

You can return serviceRunning method from another method like below and you can subscribe to main method(getUsers()), which is your requirement

getUsers() {
  return this.serviceRunning();
}

Upvotes: 8

Related Questions