Angular 5(Angular 2+),第二名后卫不等待第一名后卫完成http请求

时间:2018-01-13 16:29:55

标签: javascript angular typescript request

我有一个应用程序,其中有两个警卫(AuthGuard - 用于登录用户,AdminGuard - 用于管理员)。首次加载时,AuthGuard会发出http请求以从API获取用户信息。问题是当您尝试使用两个警卫访问路由时,AdminGuard不会等待AuthGuard完成请求并设置用户,以便AdminGuard可以检查用户的角色,并且应用程序中断。我知道它因为用户未定义而中断。 我正在寻找一个解决方案,让第二个后卫等待第一个完成。

{
    path: 'admin',
    component: AdminComponent,
    canActivate: [AuthGuard, AdminGuard]
},

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(
    private authService: AuthService,
    private http: HttpClient) { }

    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {

        return this.http.get('https://jsonplaceholder.typicode.com/users').map(res => {
            console.log('Auth Guard.');
            console.log(res);
            this.authService.user = {role: 'admin'};

            return true;
     });

         return false;
    }
}

@Injectable()
export class AdminGuard implements CanActivate {
    constructor(private authService: AuthService) { }

    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {

        console.log('Admin Guard.');
        console.log(this.authService.user);

        if (this.authService.user.role === 'admin') {
             return true;
        }

        return false;
   }

}

这是一个plnker链接 - http://plnkr.co/edit/EqgruNjogTJvsC1Zt5EN?p=preview

1 个答案:

答案 0 :(得分:0)

非常重要的一点是,AuthGuarduser进行异步调用,我们不知道什么时候会被解决。其他代码是同步,并且会立即执行而无需等待此异步调用(这就是undefinedAdminGuard的原因)。

但您可以强制observable等待,同时您的HTTP呼叫将得到解决:为此,您可以存储可观察订阅(因为您正在使用{{ 1}},但您也可以使用promiseAuthService进行AuthGuard(使用以下行进行HTTP调用):

this.authService.subscription$ = this.http.get('https://jsonplaceholder.typicode.com/users');

现在您的订阅位于AuthService,您需要的所有内容都是subscribe两个警卫(您在案例中使用.map()):

<强> AuthGuard:

return this.authService.subscription$.map(res => {
  this.authService.user = {role: 'admin'};
  return true;
});

<强> AdminGuard:

return this.authService.subscription$.map(res => {
  if (this.authService.user.role === 'admin') {
    return true;
  }
});

这是工作的plunker: http://plnkr.co/edit/R2Z26GsSvzEpPdU7tOHO?p=preview

如果您在控制台中看到"AuthGuard returns TRUE!""AdminGuard returns TRUE!" - 一切都应该可以正常工作。我还记录了this.authService.userAuthGuard的{​​{1}}变量。