与订阅的observable相关的注销权限错误

Ell*_*son 9 firebase firebase-authentication angularfire2 angular

我有一个组件,我订阅了一个observable来从Firebase中提取数据.相关的订阅代码类似于:

[ 注意:下面更新/更正的代码.]

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

必须对用户进行身份验证才能查看此组件,并且我有一个确保这一点的路由防护.

但是,当我注销时,我收到此错误:

客户端无权访问所需数据

我正在退出以下内容:

// this.auth is an injected FirebaseAuth instance
this.auth.logout();
this.router.navigate(['/login']);
Run Code Online (Sandbox Code Playgroud)

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

任务订阅和注销功能位于我的应用程序的不同部分.如果他们在同一个地方,我想我可以unsubscribe在我退出时调用订阅上的方法.但即便如此,在我的logout方法中坚持使用此订阅取消逻辑似乎很麻烦.我不太清楚如何处理这件事.

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

在Alexander Leonov关于重复分配的评论之后更新了代码

亚历山大指出我this.tasks两次分配给该物业.好点子!这段代码不正确.我没有将订阅分配给一个属性.代码应该如下所示:

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

感谢你指出这一点,亚历山大.

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

我能够通过Alexander Leonov关于取消订阅ngOnDestroy我的组件的评论来解决这个问题.

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

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

ngOnDestroy() {
  this.subscription.unsubscribe();
}
Run Code Online (Sandbox Code Playgroud)

解决方案的另一部分涉及在我的顶级组件AppComponent中订阅AngularFire auth observable.如果经过身份验证,则会重定向到一条路由; 如果没有,它会重定向到另一条路线:

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

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

Ale*_*nov 6

你搞砸了一下.您使用this.tasks两者来保留订阅:

this.tasks = this.af.database.list(...)
Run Code Online (Sandbox Code Playgroud)

以后作为任务存储:

subscribe(tasks => this.tasks = tasks)
Run Code Online (Sandbox Code Playgroud)

你需要选择力量的一面.:)

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

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

ngOnDestroy() {
    this.subscription.unsubscribe();
}
Run Code Online (Sandbox Code Playgroud)