问题
I am using Angular 4.3.5. Our app has "programs" that a user can be "subscribed" to. I have a router guard function that looks like this:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const programName = route.params['program_name'];
const programId = this.programService.getIdForName(programName);
if (this.userService.isLoggedIn() && this.subscriptionService.isSubscribed(programId)) {
return true;
} else {
this.router.navigate(['']);
return false;
}
}
To get the program id, I need to call the server. To get the list of subscriptions for the user and determine if they are subscribed to this particular program, I need to call the server.
The server calls are asynchronous using RxJS. However, my canActivate function is constrained to return a boolean. I am unsure of how to bridge this async/sync programming gap.
In RxJava, for example, I could call toBlocking() to wait for the HTTP call to resolve. But there is no such operator in RxJS. I've tried toArray(), and take(1).toArray()[0], but nothing seems to work.
In fact, I'd like to push this async/sync bridge down lower; i.e. I want subscriptionService.isSubscribed(programId) to return a boolean instead of a Observable<boolean>, because I can cache the list of subscriptions in the SubscriptionService, so that I don't need to call the server every time; but I don't think that changes the programming challenge.
回答1:
The canActivate function can return an Observable<boolean>.
回答2:
There is no such thin as blocking in JS.
Angular can handle a returned observable
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const programName = route.params['program_name'];
return this.programService.getIdForName(programName).map(pn => {
if (this.userService.isLoggedIn() && this.subscriptionService.isSubscribed(programId)) {
return true;
} else {
this.router.navigate(['']);
return false;
}
});
}
来源:https://stackoverflow.com/questions/45886395/wait-for-rxjs-operation-to-blocking