Angular2: Nested Observables in Guard

2019-07-28 16:52发布

问题:

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...

回答1:

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.