与订阅的可观察对象相关的注销权限错误

Logout permission error related to subscribed observable

我有一个组件,我在其中订阅了一个可观察对象以从 Firebase 中提取数据。相关的订阅代码类似于:

[注: updated/corrected 代码如下。]

// in my component
ngOnInit() {
  // this.af is an injected AngularFire2 instance
  this.tasks = this.af.database.list('/tasks')
    .subscribe(tasks => this.tasks = tasks);
}

用户必须经过身份验证才能查看此组件,我有一个路由保护来确保这一点。

但是,当我注销时出现此错误:

Client doesn't have permission to access the desired data

我正在注销:

// this.auth is an injected FirebaseAuth instance
this.auth.logout();
this.router.navigate(['/login']);

错误发生在路由器 navigate 方法被调用之前。问题是我有一个打开的 Web 套接字连接的活动任务观察者订阅,在调用 logout 方法后立即出错,因为用户不再经过身份验证。

任务订阅和注销功能位于我的应用程序的不同部分。如果他们在同一个地方,我想我可以在注销时调用订阅的 unsubscribe 方法。但即便如此,在我的 logout 方法中加入这个订阅取消逻辑似乎很麻烦。我不太确定如何处理这个问题。

如何在注销时取消对任务观察器的订阅?

在 Alexander Leonov 关于重复赋值的评论后更新了代码

Alexander 指出我对 this.tasks 属性 赋值了两次。好点子!这段代码不正确。我没有将订阅分配给 属性。代码应如下所示:

ngOnInit() {
  // this.af is an injected AngularFire2 instance
  this.af.database.list('/tasks')
    .subscribe(tasks => this.tasks = tasks);
}

感谢您指出这一点,Alexander。

解决方案:我最终做了什么

我能够通过 Alexander Leonov 关于在我的组件中使用 ngOnDestroy 退订的评论部分解决这个问题。

在我的任务组件中使用他的代码:

ngOnInit() {
  this.subscription = this.af.database.list('/tasks')
    .subscribe(tasks => this.tasks = tasks);
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}

解决方案的另一部分涉及订阅我的顶级组件 AppComponent 中可观察到的 AngularFire 身份验证。如果通过身份验证,它将重定向到一条路线;如果不是,它将重定向到另一条路线:

this.authService.auth$.subscribe((currentUser) => {
  if (currentUser) {
    this.router.navigate(['/tasks']);
  } else {
    this.router.navigate(['/login']);
  }
});

注销时,会通知此订阅并将用户重定向到登录路由。这一系列事件最终触发了我的组件上的 ngOnDestroy 方法,该方法取消了 AngularFire 可观察任务的订阅。

你有点搞砸了。您同时使用 this.tasks 来保持订阅:

this.tasks = this.af.database.list(...)

以后作为任务存储:

subscribe(tasks => this.tasks = tasks)

您需要选择力的一侧。 :)

要回答您的问题,需要更多关于您的应用程序如何工作的信息。如果您在用户登录时在 ngOnInit() 中初始化连接,那么我的猜测是在注销时您的组件被杀死,因此您也可以实现 OnDestroy 并在那里终止订阅,如下所示:

// in my component
ngOnInit() {
  this.subscription = this.af.database.list('/tasks')
    .subscribe(tasks => this.tasks = tasks);
}

ngOnDestroy() {
    this.subscription.unsubscribe();
}