javascript - Angular 5(Angular 2+),第二个守卫不等待第一个守卫完成http请求

标签 javascript angular typescript request

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

{
    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;
   }

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

最佳答案

需要理解的非常重要的一点是,在 AuthGuard 中,您进行了一个异步 调用,我们不知道它何时会被解析。其他代码是同步的,将立即执行而无需等待此异步调用(这就是为什么user 未定义)。

但是您可以强制 AdminGuard 等待,而您的 HTTP 调用将被解析:为此,您可以存储 Observable Subscription(因为您正在使用 observable,但你也可以用 promise 做同样的事情)到 AuthGuardAuthService(你在其中创建 HTTP调用)使用以下行:

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

现在你的订阅是在AuthService中,你所需要的只是在两个守卫中订阅(你正在使用.map()在你的情况下):

AuthGuard:

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

管理 guard :

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!” - 一切正常。我还从 AuthGuardAdminGuard 中记录了 this.authService.user 变量。

关于javascript - Angular 5(Angular 2+),第二个守卫不等待第一个守卫完成http请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48241851/

相关文章:

Javascript 更改特定对象属性

javascript - 将集合映射到对象

javascript - 如何在 JavaScript 中指定最小值和最大值时使用递归创建数组

angular - NgRx 中的 reducer 增强器相当于什么?

angular - Angular 中没有将 "exportAs"设置为 "ngModel"的指令

reactjs - 如何使用 React 正确编写条件类型?

javascript - 使用 javascript 添加(而不是替换)css 类

Angular5:将 Angular 应用程序部署到多个客户端

angular - 找不到 Azure B2C 自定义 UI、Angular、CSS 文件

angular - 如何对依赖于元素高度的组件进行单元测试( Angular 为 5)?