我有一个组件,我在其中订阅了一个可观察对象以从 Firebase 中提取数据。相关的订阅代码类似于:
[注意:更新/更正了下面的代码。]
// 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();
}
关于angular - 与订阅的可观察对象相关的注销权限错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40900800/