Search code examples
angularrxjsangular-httpclient

how to make multiple http calls synchronously at different levels in angular 2 using rxJS


I want to make multiple http calls synchronously at different levels in angular 2 using rxJS For Eg , I am having a resolver service which handles 5 api calls like a,b,c,d and e.

I want them to execute in this order and I am not using any of those output values as input so I need all responses only at end.

first a should be called and once api is completed second b,c, d third after b,c,d completed then e should be called

In activated Route , I need to retrieve those values and use it I have already tried below stuff but I am getting response of A and E only and I could not able to fetch the values from inner observable

resolve(a,b){
 return A.flatMap(data=> {
      return forkJoin (
                 B,C,D)
                  }).flatMap(xres => {
                                 return E
                                 })
}
route.data.dataA
route.data.dataBCD
route.data.dataE

Solution

  • If you have one resolver that takes care of all 5 requests, in order to ensure their order of execution, then it would make sense to return the results of those 5 requests as one element. Try with the following:

    import {Observable, forkJoin} from 'rxjs';
    import {mergeMap, map} from 'rxjs/operators';
    
    interface AFoo { }
    interface BFoo { }
    interface CFoo { }
    interface DFoo { }
    interface EFoo { }
    
    class FooService {
      doA(): Observable<AFoo> { throw new Error("Not implemented"); }
      doB(): Observable<BFoo> { throw new Error("Not implemented"); }
      doC(): Observable<CFoo> { throw new Error("Not implemented"); }
      doD(): Observable<DFoo> { throw new Error("Not implemented"); }
      doE(): Observable<EFoo> { throw new Error("Not implemented"); }
    }
    
    interface CompositeFoo {
      aFoo: AFoo;
      bFoo: BFoo;
      cFoo: CFoo;
      dFoo: DFoo;
      eFoo: EFoo;
    }
    
    export class FooResolver implements Resolve<CompositeFoo>{
      constructor(private fooService: FooService) { }
      resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<CompositeFoo> {
        const forked$ = forkJoin(this.fooService.doB(), this.fooService.doC(), this.fooService.doD())
                        .pipe(map(([bFoo, cFoo, dFoo]) => ({ bFoo, cFoo, dFoo })));
        return this.fooService.doA()
          .pipe(
          mergeMap(aFoo => forked$.pipe(map(forked => ({ ...forked, aFoo })))),
          mergeMap(result => this.fooService.doE().pipe(map(eFoo => ({ eFoo, ...result })))),
          map(result => ({ ...result }))
          );
      }
    }