我有一个名为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$
发出新数据,我可以看到即使守卫已“使用”且路由已激活,可观察对象仍处于活动状态。然后,我期望当我走到path: ':company'
以外的路线时它会消失,但是警卫并未被摧毁。
这使我想到我的问题:
我这样做正确吗?我希望使用防护措施来检查用户是否具有任何权限,但是同时我只想执行一次HTTP请求权限(在导航到path: ':company'
或其任何子级时)。恐怕如果使用这样的防护措施,由于有大量的观察者,它会及时减慢整个应用程序的速度。
答案 0 :(得分:2)
从子级路由内的permissions $中释放新数据我可以看到,即使防护已被“使用”且路由已激活,可观察对象仍处于活动状态。
首先,permissions$
仍处于活动状态,因为您从未退订过自己的后卫。棱角分明的护卫为单身。
即使守护程序不是单例,在订阅中仍通过this.permissions
引用守护程序的实例,并且如果您的observable作为auth服务中的变量存在(我假设是单例),则此绑定将还可以防止垃圾收集。
这使我想到了一个问题:我这样做正确吗?我希望使用防护措施来检查用户是否具有任何权限,
最好在您的监护人那里发出请求,例如获取权限。
但同时我只想对权限执行一次HTTP请求(当导航到path:':company'或其任何子级时)。
如果您只想发出一次请求,则应考虑在身份验证服务中使用shareReplay,以便将来所有连接的实例都使用相同的先前发出的值。