首页 > 解决方案 > 角度路由:当从父路由守卫导航到子路由时,父路由守卫在无限循环中触发

问题描述

假设我们有一个包含许多用户个人资料的网站。站点仅适用于经过身份验证的用户。我希望能够输入空 URL,然后在身份验证后我将被转发到我的个人资料。我希望能够直接输入另一个用户的个人资料 URL,然后在身份验证后我将被转发到他的个人资料。

路由:

{
   path: '',
   canActivate: AuthGuard,
   children: {
     path: ':userId',
     component: UserProfileComponent
   }
}

警卫:

export class AuthGuard implements CanActivate {
  constructor(
    private router: Router,
    private authService: AuthService
  ) {}

  async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean | UrlTree> {
    const isLoggedIn: boolean = await this.authService.checkLogin();
    if (!isLoggedIn) {
      this.authService.login();
      return false;
    }
    if (state.url === '/') {
      const loggedInUser = this.authService.getCurrentUser();
      return this.router.createUrlTree([loggedInUser.id]);
    } else {
      return true;
    }
  }
}

问题是当我输入一个空 URL 时,AuthGuard 被触发两次,我需要进行此检查

if (state.url === '/') ...

避免无限循环。

如何以这种方式实现它

this.authService.checkLogin()

只会被调用一次?

标签: angularangular-router

解决方案


回答我自己的问题似乎在这里使用'good old' setTimeout 有效。它强制重定向在“NavigationEnd”事件发生后发生。但这真的是一个好方法吗?

export class AuthGuard implements CanActivate {
  constructor(
    private router: Router,
    private authService: AuthService
  ) {}

  async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean | UrlTree> {
    const isLoggedIn: boolean = await this.authService.checkLogin();
    if (!isLoggedIn) {
      this.authService.login();
      return false;
    }
    if (state.url === '/') {
      const loggedInUser = this.authService.getCurrentUser();
      setTimeout(() => this.router.navigate([loggedInUser.id]), 0);
    }
    return true;
  }
}

推荐阅读