【发布时间】:2022-01-27 18:55:32
【问题描述】:
有一个身份验证服务,在身份验证后立即获取数据:
export class AuthService {
profile: BehaviorSubject<Profile| undefined> = new BehaviorSubject<Profile| undefined>(undefined);
constructor(private auth: Auth, private http: HttpHandlerService) {
//login and fetch profile data
this.auth.isAuth.subscribe(isAuth => {
if (isAuth) {
this.http.getProfile.subscribe(profile => this.profile.next(profile))
}
});
}
}
应用程序全局需要配置文件数据(在标题等中)。
问题: 在页面刷新/页面重新加载时,我的 Guard 不会等待 Authsevice 完成,因此我无法访问我的配置文件数据。
似乎唯一可行的解决方案是将数据获取逻辑移到 Guard 中,请参阅AuthGuard doesn't wait for authentication to finish before checking user
但是,就我而言,这还不够。我需要全局的个人资料数据,如果我在受保护的路线上,它不仅会被获取。
所以我要做的就是确保在守卫工作之前获取我的数据。
我目前的解决方案:
export class ProfileGuard {
constructor(private auth: AuthService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.auth.profile.pipe(
skipWhile(profile => !profile),
tap(profile=> {
if (profile && profile.banned) {
this.router.navigate(['/banned']).then();
}
}),
take(1),
map(() => true)
);
}
我有两个问题:1)我需要将这个额外的逻辑添加到我所有的守卫中! 2)这个解决方案感觉很hacky。
真的没有更简单/更好的方法可以在刷新/页面加载后立即在 Guard 中检查我的个人资料数据吗?
【问题讨论】:
-
什么意思“在页面刷新/页面重新加载时,我的 Guard 不会等待 Authsevice 完成,因此我无法访问我在 Guard 中的个人资料数据。”?服务没有初始化?顺便说一句,您是否有意使用
skipWhile而不是filter?您的代码将允许未定义/虚假值通过 if 您曾经获得一个通过skipWhile条件的值,但filter不会。 -
嗯我将如何初始化服务?我的意思是我在 isAuth 变为 true 后立即获取数据。在页面刷新时,这可能需要一点时间,我的守卫不会等待。
-
啊,关于 skip 虽然它没有区别,因为 take(1) 会发出收到的第一个值。这个想法是简单地等到身份验证配置文件返回一个有效值。
-
好吧,如果您使用
take,您是正确的,我没有考虑这一点,很好。否则,您的代码应该可以正常工作,我制作了一个小的Stackblitz example,它的工作方式相同,没有问题。您确定该服务之前没有发出任何内容。至于您最初的问题是否有更好的方法,请查看this question。
标签: angular typescript rxjs angular2-routing angular-router-guards