Angular canLoad守卫无法获取AuthenticationService更新值问题解决
问题解决说明
根本原因
你遇到的问题是AuthenticationService被重复注册,生成了两个完全独立的服务实例:
- 服务本身声明了
@Injectable({ providedIn: 'root' }),会在根注入器生成一个全局单例实例,你的路由守卫AuthGuard注入的就是这个实例 - 你又在
LoginModule的providers数组中再次声明了AuthenticationService,会在Login模块的子注入器生成另一个独立实例,登录组件中注入的就是这个实例
你在登录组件调用login()修改的是Login模块本地实例的状态,根实例的状态始终是false,因此守卫永远校验不通过。
修复方案
第一步:删除重复的服务注册
打开LoginModule代码,删除providers数组中的AuthenticationService声明即可,根级注册的单例服务会自动注入到所有模块中,无需在子模块重复注册:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { LoginComponent } from './login.component'; import { NzFormModule } from 'ng-zorro-antd/form'; import { LoginRoutingModule } from './login-routing.module'; import { NzInputModule } from 'ng-zorro-antd/input'; import { NzButtonModule } from 'ng-zorro-antd/button'; @NgModule({ declarations: [ LoginComponent ], imports: [ CommonModule, NzFormModule, LoginRoutingModule, NzInputModule, NzButtonModule ] // 移除这行代码:providers: [AuthenticationService] }) export class LoginModule { }
完成这步操作后问题就已经解决,全应用只会存在一个AuthenticationService实例,守卫可以正常读取到登录状态的更新。
可选优化:使用响应式写法避免时序问题
canLoad守卫本身支持返回Observable<boolean>类型,配合BehaviorSubject的流特性可以避免直接取快照值可能出现的时序问题,写法更符合RxJS最佳实践:
- 给
AuthenticationService新增返回登录状态流的方法:
// AuthenticationService 新增代码 public isLoggedIn$() { return this.isUserLoggedIn.asObservable(); }
- 修改
AuthGuard的实现:
import { Injectable } from '@angular/core'; import { CanLoad, Route, UrlSegment } from '@angular/router'; import { Observable } from 'rxjs'; import { take, map } from 'rxjs/operators'; import { AuthenticationService } from '../services/auth.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanLoad { constructor(private authService: AuthenticationService) {} canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> { return this.authService.isLoggedIn$().pipe( take(1), // 只取一次状态值就终止流 map(isLoggedIn => isLoggedIn) ); } }
另外你在AppModule的providers中注册了AuthGuard,而AuthGuard本身已经是根级单例,这里的注册可以删除,不会影响功能只是冗余配置。
内容的提问来源于stack exchange,提问作者Max M
相关产品推荐
相关产品推荐

