首页 > 解决方案 > Angular 路由是否订阅了 RouteGuards 返回的 observable?

问题描述

我对 Angular 路由如何处理守卫返回的 observables 感到有些困惑。采取以下路线守卫:

export class AuthenticationGuard implements CanActivate {

  constructor(private sessionQuery: SessionQuery, private router: Router){}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    const loginPage = this.router.parseUrl('/login')

    return this.sessionQuery.loggedIn$.pipe(
      map((loggedIn: boolean): boolean | UrlTree => {
        console.log('loggedIn emitted: ', loggedIn)
        return loggedIn ? true : loginPage
      })
    )
  }
}

守卫返回一个映射this.sessionQuery.loggedIn$trueiftrueloginPageif的 observable false

但是,我希望路由守卫会订阅 observable: this.sessionQuery.loggedIn$observable ,这样当它重新发出时,路由守卫中的逻辑会被重新评估。

然而,测试似乎表明它没有。如果我在应用程序的其他地方订阅这个 observable,我可以看到它重新发出,但console.log我在上面代码中的调用不会触发。

我希望路由守卫在loggedIn$observable 发出时触发自动注销false

如果路线没有订阅守卫,那么守卫首先返回一个可观察的有什么意义?我觉得我在这里缺少一些东西......

标签: angulartypescriptangular-route-guards

解决方案


您必须实现“在sessionQuery.loggedIn$其他地方发出 false 时登录的路由”的逻辑,可能是在急切地注入其父模块的服务中(以确保它被实例化)。

要检查 Angular 对返回的 Observable 做了什么,您可以返回以下内容。我的猜测是,Angular 获得了第一个发出的值并取消订阅。

return new Observable<boolean | UrlTree>((subscriber) => {
    const subscription = this.sessionQuery.loggedIn$.pipe(
      map((loggedIn: boolean): boolean | UrlTree => {
        console.log('loggedIn emitted: ', loggedIn)
        return loggedIn ? true : loginPage
      })
    ).subscribe(subscriber);

    return () => {
        // called when no subscriber is left
        console.log('unsubscribed');
        subscription.unsubsribe();
    };
});

推荐阅读