【问题标题】:How can I unsubscribe from this subscription?如何取消订阅此订阅?
【发布时间】:2022-01-19 20:13:56
【问题描述】:

我有一个 PolicyGuard 和一个方法 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)

canActivate 中,我创建了一个 observable,并在这个 observable 内部订阅了一个从 AbilityService 检索到的 Observable。

我从 AbilityService 检索到的 observable 监听用户“策略”/“能力”的变化。

当我对用户的“策略”进行更改并使用 Socket.io 将这些更改推送到客户端时,这会变得非常混乱,因为当我不希望它发生时,可能会发生页面重定向到主页(一个订阅运行obs.next(true),而另一个订阅路由回家并运行obs.next(false))

有没有一种方法可以让我在离开订阅的页面时取消订阅?

@Injectable()
export class PolicyGuard implements CanActivate {

    constructor(protected router: Router, private abilityService: AbilityService) {}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        console.log("PolicyGuard() - canActivate()");

        return new Observable<boolean>(obs => {
            const observable = this.abilityService.getAbility();
            observable.subscribe(ability => {
                const can = ability.can(route.data.action, route.data.subject);

                if (can) {
                    obs.next(true);
                }
                else {
                    this.router.navigate(['/home']);
                    obs.next(false);
                }
            });
        });
    }
}

【问题讨论】:

  • 在订阅前使用管道尝试 rxjs take(1)。它将需要一次发射并取消订阅
  • 我试过了。这样做的问题是,如果您位于应用程序中您不再有权访问的页面上(由于用户策略正在更新),那么该页面不会将您踢回首页。我正在考虑以某种方式使用诸如 takeUntil() 或 takeWhile() 之类的东西,但不确定使用什么作为条件。

标签: angular typescript routes observable angular-route-guards


【解决方案1】:

您当前创建了一个额外的 Observable,我认为这不是必需的。您可以简单地返回 this.abilityService.getAbility() 并使用 RxJS map 运算符转换返回值。这样 Angular 就会接管并处理来自 Observable 的订阅。

看起来像这样:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  console.log("PolicyGuard() - canActivate()");

  return this.abilityService.getAbility().pipe(
    map(ability => {
      const can = ability.can(route.data.action, route.data.subject);
     
      if (!can) {
        this.router.navigate(['/home']);
      }
      return can;
    });
  );
}

angular.io 上的 canActivate 示例做了类似的事情,只是没有 map 运算符。

【讨论】:

  • 使用此解决方案时,我遇到与使用 take(1) 相同的问题,如果用户在他们不再有权访问的页面上(由于用户策略/能力正在更新),则不会路由用户返回首页。所以我想,不知何故,我可以在用户规则更新后再次触发 canActivate() 方法而不刷新页面。
  • 你的意思是没有踢回家,政策发生变化,但用户没有直接导航到家?
  • 是的,因为订阅在运行一次后就结束了,并且当用户通过 Socket.io 更新规则时,不会再次调用路由守卫。有没有办法在不刷新页面的情况下触发canActivate()方法再次运行?
猜你喜欢
  • 2012-03-14
  • 2015-08-24
  • 2019-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多