Angular canActivate路由守卫等待authService.isLoggedIn状态更新问题求助
问题根因
AuthLogin方法中调用异步的SetUserData时没有加await,不等用户数据写入操作完成就直接跳转到首页,此时路由守卫读取localStorage时还没有最新的用户登录信息,判定为未登录就重定向到了登录页。- 当前
AuthGuard是同步校验逻辑,无法等待登录状态更新完成再执行判断,且原有逻辑存在缺陷:未登录时触发跳转后仍然返回true,不符合路由守卫的返回规范。
具体修改方案
1. 修改 auth.service.ts
- 给
SetUserData方法补充写入localStorage的逻辑(当前代码只更新了Firestore,没有写入本地存储,这也是isLoggedIn不能及时拿到最新状态的核心原因) - 在
AuthLogin中调用SetUserData前加await,等待写入操作全部完成后再跳转首页
修改后参考代码:
async AuthLogin(provider: firebase.auth.AuthProvider) { try { const result = await this.afAuth.auth.signInWithPopup(provider); // 加await等待用户数据写入完成再跳转 await this.SetUserData(result.user); this.router.navigate([""]); } catch (error) { window.alert(error); } } SetUserData(user) { const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.uid}`); const userData: User = { uid: user.uid, email: user.email, displayName: user.displayName, photoURL: user.photoURL, emailVerified: user.emailVerified, }; // 补充写入localStorage的逻辑 localStorage.setItem('user', JSON.stringify(userData)); return userRef.set(userData, { merge: true, }); }
2. 优化 auth.guard.ts
调整守卫逻辑,支持异步判断,同时修正返回值的逻辑错误。更稳妥的方式是直接使用AngularFire自带的authState observable实现状态监听,它会等待登录状态完全初始化完成后再执行校验,避免本地存储读写延迟带来的问题:
import { map, take } from 'rxjs/operators'; @Injectable({ providedIn: "root", }) export class AuthGuard implements CanActivate { constructor(public authService: AuthService, public router: Router) {} canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return this.authService.afAuth.authState.pipe( take(1), map(user => { const isLoggedIn = !!user && user.emailVerified; if (!isLoggedIn) { // 直接返回UrlTree对象完成重定向,符合Angular路由守卫规范 return this.router.parseUrl('/login'); } return true; }) ); } }
内容的提问来源于stack exchange,提问作者artworkjpm
相关产品推荐
相关产品推荐

