Matt Matt - 2 months ago 38
TypeScript Question

Angular2: Nested Observables in Guard

I have a Guard protecting a certain route. In the

canActive
method I need to make two http requests, at which the second one is triggered based on the response of the first one. However, the second request is never made and I assume it is about the nested construct of returning Observables.

1 canActivate(route: ActivatedRouteSnapshot,
2 state: RouterStateSnapshot) : Observable<boolean>|boolean {
3 return this.provider.getA().map(
4 dataA => {
5 return this.provider.getB().map(
6 dataB => {
7 return (dataB.allowed);
8 }
9 );
}
);
}


Both getA() and getB() return the following:

getA() : Observable<any> {
return this.http.post(URL,payload).
map(response => response.json());


};

The code is simplified, but you may assume that getA() and getB() work properly. getA() is sent alright over the network when the Guard is called, getB() is never sent, though. The debugger exits silently in line 5.

One more thing, TypeScript shows a warning that probably tells me solution already, however, I'm too much a Noob with Observables in particular to know what to do with it:

Observable<Observable<boolean>>' is not assignable
to type 'Observable<boolean>'


To make a guess, the construct of Observables never resolves, that's why there is no warning and I wait until the end of time. My naive notion was that, as long as any Observable will return a boolean (as done in line 7), the subscriber would know how to handle it.

I'm happy to read your hints. Off to bed...

Answer

You should use switchMap here:

return this.provider.getA().switchMap(
  dataA => {
    return this.provider.getB().map(
      dataB => {
        return (dataB.allowed);
      }
    );
  }
);

In your code, you are creating an Observable of Observables. switchMap flattens that structure and emits the emitted items of B through A.