angularservicerxjsconcatmap

Angular - RxJS ConcatMap - Return Data From Both Service Calls


Probably a basic question, but I have an Angular app that makes a backend service call to retrieve some data and then uses that data to make another backend service call.

The second service call is dependent on the first completing successfully, so I use the concatMap() function from RxJS.

However, my code below is only returning the data for the second service call. I need all the data returned from both service calls.

Have a feeling I'm messing up the .pipe call, but not making much progress. Thanks in advance.

getData(id: String): Observable<any[]> {
return this.http.get<any>(`${this.baseUrl}/path/${id}`).pipe(
  concatMap(
    evt =>
      <Observable<any[]>>(
        this.http.get<any[]>(
          `${this.baseUrl}/path/relatedby/${evt.child_id}`
        )
      )
  ),
  retry(3),
  catchError(this.handleError("getData", []))
);}

Solution

  • The pipe function combines the given functions(supplied as arguments) and executes them in series, and finally returns the FINAL OUTPUT after going through the stages. That's why you're getting the result from the second call only, because that was the last function in the pipe (last function which returned a value).

    eg: lets check this out

    const filterOutEvens = filter(x => x % 2)
    const double = map(value => value * 2);
    const sum = reduce((acc, next) => acc + next, 0);
    
    Observable.range(0, 10).pipe(
      filterOutEvens, 
      double, 
      sum)
     .subscribe(console.log); // 50
    

    here, from [1, 2, 3, 4, 5, 6 ,7, 8, 9,10], it first filters out even numbers, giving [1,3,5,7,9], which is passed to the next function (double), which doubles every element of the given array, giving [2,6,10,14,18], which is passed to the next function in pipe, which is sum (adds up the elements in the array). The sum function is the LAST function in the pipe, and returns 50, which is not only the return value of sum(), but also the whole pipe() as well.

    example code taken from:https://blog.hackages.io/rxjs-5-5-piping-all-the-things-9d469d1b3f44

    Edit
    If u really want the data from both requests, you could pack the results of the first request in the result of second request using 'map' operator

     getData(id: String): Observable<any[]> {
      return this.http.get<any>(`${this.baseUrl}/path/${id}`).pipe(
     concatMap(
        evt =>
           <Observable<any[]>>(
              this.http.get<any[]>(
          `${this.baseUrl}/path/relatedby/${evt.child_id}`
            ).map(res =>( {"response1":evt, "response2":res}) )
      )
     ),
     retry(3),
     catchError(this.handleError("getData", []))
     );}