2

I have an Angular route which uses a parameter :client_name, and a service with method getClientDetails(client_name) to fetch data from an HTTP API based on :client_name. Both are Observable methods working on their own, but when I combine the 2 observables then the API call runs before the params has been fetched (client_name is undefined):

    this.route.params.subscribe(params => {
  this.client_name = params['client_name'];
  this.dataService.getClientDetails(this.client_name).subscribe(
    clientdata => {
      this.client = clientdata;
      console.log(clientdata);
    });

How can I chain both observables so the API only runs once the :client_name is returned?

Yann
  • 877
  • 14
  • 25

1 Answers1

5

We can make use of pipeable RxJS operators for this scenario.

First, we can use RxJS's mergeMap to map over the observable values from route into an inner observable. If params and params['client_name'] are defined, we assign params['client_name'] to the client_name property, which is similar to your initial code. Then, we call the getClientDetails() method from dataService. If the params do not exist, we convert null into an observable, and return it.

Subsequently, the observables are returned in .subscribe() block. From there, we can assign the response to the client property.

import { mergeMap } from 'rxjs/operators';
import { of } from 'rxjs';
.
.
this.route.params.pipe(
  mergeMap(params => {
    if (params && params['client_name']) {
      this.client_name = params['client_name'];
      return this.dataService.getClientDetails(this.client_name);
    } else {
      return of(null)
    }
  })
).subscribe(response => {
  // handle the rest
  this.client = response;
})
wentjun
  • 40,384
  • 10
  • 95
  • 107
  • If I use next, error and complete structure, can we put the second subscribe into the complete block rather than `mergeMap`? – Bigeyes Jul 18 '19 at 11:14
  • @Bigeyes Hmm.. I wouldn't recommend you to do that. You can use `mergeMap` to chain the nested operations. The `complete` callback should only be used to handle any logic regarding the completion of execution of that block of code! – wentjun Jul 18 '19 at 14:20
  • All right. Actually I have several http requests that should be in order. I heard about Contact in RxJS, can we use it to chain them together? – Bigeyes Jul 18 '19 at 18:14
  • @Bigeyes `mergeMap`, and `concat`, would both work. Depending on the exact usage, you might want to use `combineLatest` or `forkJoin too`! If you still need help with that, maybe you can give me more context on the exact usage? – wentjun Jul 19 '19 at 05:29
  • Thank you for the nice reply. For example, I have two web api calls. The first one is `http get`, Once I get the returned data, I want to make the second `http post` service call. So I want to chain them together. – Bigeyes Jul 20 '19 at 11:52
  • 1
    @Bigeyes Hmm.. In that case, it would really depend on the details. For instance, if the first API request (with http get) returns a set of data, and that data is required to call the subsequent API request (http post), you will need to use `mergeMap()` – wentjun Jul 23 '19 at 08:31