Guard canActivate 在服务实例化之前运行
Guard canActivate runs before service is instantiated
这很可能是一个非常微不足道的问题,我只是从 AngularJS 背景中挑选 Angular 2+。
最简单的是,我在我的 angular 9 应用程序中实施身份验证,但我的警卫遇到了一个问题。
在我的 authentication.service.ts
服务中,我使用的是用户类型的 BehaviourSubject,并且我使用以下公共库将我的用户对象保存在 localStorage
中:https://github.com/cyrilletuzi/angular-async-local-storage
在我的 authentication.service
构造函数中,我正在做这样的事情:
constructor(private request: RequestService, private storage: StorageMap) {
this.storage.get('currentUser').subscribe((user: User) => {
this.currentUserSubject = new BehaviorSubject<User>(user);
this.currentUser = this.currentUserSubject.asObservable();
});
}
和我的 isAuthenticated
方法:
isAuthenticated() {
return this.currentUserSubject.value;
}
这很好用,但是,因为 storageMap 是一个可观察对象,它需要很少的时间才能 return,因此当我尝试检查用户是否在我的守卫中经过身份验证时:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.isAuthenticated();
}
很遗憾,this.currentUserSubject
未定义。所以守卫 运行 在 authentication.service
中的构造函数有机会正确实例化之前。
如有任何积分,将不胜感激。
更新:
我想我越来越接近了。
在我的 authentication.service 中,我的 isAuthenticated 方法现在看起来像这样(如下所示)
isAuthenticated() {
return this.currentUser
.pipe(filter(user => user));
}
虽然有错误:参数类型用户不可分配给参数类型。
此外,如果我在 canActivate 中更改我的 return 语句:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.isAuthenticated();
}
但我在控制台中得到了这个
类型 'Observable' 不能分配给类型 'Observable'。
类型 'unknown' 不能分配给类型 'boolean | UrlTree'。
类型“{}”缺少类型 'UrlTree' 中的以下属性:root、queryParams、fragment、queryParamMap
18 return this.authService.isAuthenticated();
canActivate
方法必须returnObservable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
.
据我所知,您正在 return 对象(用户)。
但是,在你的守卫中,你应该使用可观察的而不是主题。
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.authService.currentUser.pipe(map(user => !!user));
}
map
运算符的双重否定 (!!
) 将使 return 的可观察值成为布尔值。
Guards 在导航时被激活,所以在导航到 post 登录页面之前,请确保您已设置用户。
constructor(private authenticationService: AuthenticationService, private router: Router) {}
ngOnInit() {
this.handleUserChange();
}
private handleUserChange(): void {
this.authenticationService.currentUserSubject
.pipe(filter(user => user)) // falsy value check
.subscribe(user =>
{
// Navigate to post login
this.router.navigate(['home-page']);
}
}
async isAuthenticated() {
var res = await this.storage.get('currentUser').toPromise();
return res;
}
您遇到的行为的原因是,订阅是一项异步作业。所以 class 一调用订阅就完成了初始化。订阅的回调将在稍后拥有该数据时调用。在调用您的回调之前,您已被调用。
这很可能是一个非常微不足道的问题,我只是从 AngularJS 背景中挑选 Angular 2+。
最简单的是,我在我的 angular 9 应用程序中实施身份验证,但我的警卫遇到了一个问题。
在我的 authentication.service.ts
服务中,我使用的是用户类型的 BehaviourSubject,并且我使用以下公共库将我的用户对象保存在 localStorage
中:https://github.com/cyrilletuzi/angular-async-local-storage
在我的 authentication.service
构造函数中,我正在做这样的事情:
constructor(private request: RequestService, private storage: StorageMap) {
this.storage.get('currentUser').subscribe((user: User) => {
this.currentUserSubject = new BehaviorSubject<User>(user);
this.currentUser = this.currentUserSubject.asObservable();
});
}
和我的 isAuthenticated
方法:
isAuthenticated() {
return this.currentUserSubject.value;
}
这很好用,但是,因为 storageMap 是一个可观察对象,它需要很少的时间才能 return,因此当我尝试检查用户是否在我的守卫中经过身份验证时:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.isAuthenticated();
}
很遗憾,this.currentUserSubject
未定义。所以守卫 运行 在 authentication.service
中的构造函数有机会正确实例化之前。
如有任何积分,将不胜感激。
更新:
我想我越来越接近了。
在我的 authentication.service 中,我的 isAuthenticated 方法现在看起来像这样(如下所示)
isAuthenticated() {
return this.currentUser
.pipe(filter(user => user));
}
虽然有错误:参数类型用户不可分配给参数类型。
此外,如果我在 canActivate 中更改我的 return 语句:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.isAuthenticated();
}
但我在控制台中得到了这个
类型 'Observable' 不能分配给类型 'Observable'。 类型 'unknown' 不能分配给类型 'boolean | UrlTree'。 类型“{}”缺少类型 'UrlTree' 中的以下属性:root、queryParams、fragment、queryParamMap
18 return this.authService.isAuthenticated();
canActivate
方法必须returnObservable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
.
据我所知,您正在 return 对象(用户)。
但是,在你的守卫中,你应该使用可观察的而不是主题。
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.authService.currentUser.pipe(map(user => !!user));
}
map
运算符的双重否定 (!!
) 将使 return 的可观察值成为布尔值。
Guards 在导航时被激活,所以在导航到 post 登录页面之前,请确保您已设置用户。
constructor(private authenticationService: AuthenticationService, private router: Router) {}
ngOnInit() {
this.handleUserChange();
}
private handleUserChange(): void {
this.authenticationService.currentUserSubject
.pipe(filter(user => user)) // falsy value check
.subscribe(user =>
{
// Navigate to post login
this.router.navigate(['home-page']);
}
}
async isAuthenticated() {
var res = await this.storage.get('currentUser').toPromise();
return res;
}
您遇到的行为的原因是,订阅是一项异步作业。所以 class 一调用订阅就完成了初始化。订阅的回调将在稍后拥有该数据时调用。在调用您的回调之前,您已被调用。