4

我有一个名为的路由器保护PermissionGuard程序,它在此处启动

const routes: Routes = [
  {
    path: ':company',
    component: CompanyComponent,
    canActivate: [PermissionGuard],
    canActivateChild: [PermissionGuard],
    children: [
      {
        path: '',
        component: IndexComponent
      },
      {
        path: 'projects',
        loadChildren: '../projects/projects.module#ProjectsModule'
      },
    ]
  }
];

在我的内部,我PermissionGuard订阅了PermissionService这样的内容:

export class PermissionGuard implements CanActivate, CanActivateChild {

  private permissions: Permission[];

  constructor(private permissionService: PermissionService, private router: Router) {
    this.permissionService.permissions$.subscribe(
      (permissions: Permission[]) => {
        this.permissions = permissions;
      }
    );
  }

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    this.permissionService.getPermissions(next.paramMap.get('company'));
    return this.permissionService.permissionsFetchDone$
    .pipe(filter(x => x))
    .pipe(
      map(response => {
        if (this.permissions) {
          return true;
        } else {
          this.router.navigate(['/forbidden']);
        }
      })
    );
  }
}

并根据这些数据执行必要canActivate或检查。canActivateChild通过从子路由内部添加console.log()和发出新数据,permissions$我可以看到 observable 仍然处于活动状态,即使防护已被“使用”并且路由已激活。然后我期待当我去外面的路线时它会消失path: ':company',但是守卫没有被摧毁。

这让我想到了我的问题: 我这样做正确吗?我希望使用警卫检查用户是否有任何权限,但同时我只想执行一次 HTTP 权限请求(导航到path: ':company'或其任何子级时)。恐怕如果我使用这样的守卫,由于大量的观察者,它会及时减慢整个应用程序。

4

1 回答 1

3

从子路由中的权限 $ 发出新数据我可以看到 observable 仍然处于活动状态,即使防护已被“使用”并且路由已激活。

首先,permissions$它仍然处于活动状态,因为您从未在您的后卫中退订。并且 Angular 将守卫创建为单例。

即使守卫不是单例,守卫的实例仍然通过订阅在订阅中引用this.permissions,并且如果您的可观察对象作为变量存在于您的身份验证服务(我假设是单例)中,则此绑定也将阻止垃圾收集。

这让我想到了我的问题:我这样做正确吗?我希望使用警卫检查用户是否有任何权限,

在你的警卫中发出请求是完全可以的,例如获取权限。

但同时我只想执行一次 HTTP 权限请求(导航到路径:':公司'或其任何子级时)。

如果您只想发出一次请求,那么您应该考虑在您的身份验证服务中使用shareReplay,以便所有未来连接的实例都使用相同的先前发出的值。

于 2018-10-22T19:39:39.383 回答