我的服务中有一个简单的功能:
/**
* Funtion to check if the user logged in has admin rights
*/
isAdmin(user_id: string) {
var adminTemp: boolean;
this.httpClient
.get(`${this.urk}/${user_id}`)
.subscribe((data: any) => {
if (data.includes('Admin')) {
adminTemp = true;
} else {
adminTemp = false;
}
});
return adminTemp;
}
此函数在canActivate
函数中调用,该函数需要布尔值来确定用户是否为管理员。
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if(this.loginService.isAdmin('123')){
return true;
}
else{
return this.router.parseUrl("/admin/logout");
}
}
问题是,在进行api调用之前,它会获取一个未定义的值,并将用户标记为非admin。我理解这种情况是因为订阅本身就是一个异步调用。我找不到任何其他方法来弄清楚如何做到这一点,因为在知道他们是否是用户之前,必须处理api响应,否则我会使用一个简单的返回语句。我应该如何继续?
您的问题是没有利用Reactive编程(这是Angular借助Rxjs带来的最佳优势之一(。
在您的函数isAdmin((中,它调用异步的http,您没有确保在返回adminTemp
时,它已经被分配了http结果中的值。
相反,你不应该从asAdmin订阅http调用,只需将其作为可观察的返回,并让canActive处理它。因此,try not to subscribe if you can avoid it
将帮助你提高效率。
isAdmin(user_id: string): Observable<boolean> {
return this.httpClient
.get(`${this.urk}/${user_id}`)
.pipe(
switchMap((data) => {
if (data.includes('Admin')) {
return of(true);
} else {
return of(false);
}
})
);
}
优点是canActive((也可以返回Observable,因此您可以很容易地在canActive((中使用它,如下所示:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.loginService.isAdmin('123').pipe(
map((res) => {
if (res) {
return true;
} else {
return this.router.parseUrl("/admin/logout");
}
})
);
}