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

Posted

技术标签:

【中文标题】与订阅的 observable 相关的注销权限错误【英文标题】:Logout permission error related to subscribed observable 【发布时间】:2017-04-15 12:14:48 【问题描述】:

我有一个组件,我订阅了一个 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);

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

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

客户无权访问所需数据

我正在注销,例如:

// 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 Leonov 关于在我的组件中使用 ngOnDestroy 取消订阅的评论部分解决了这个问题。

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

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


ngOnDestroy() 
  this.subscription.unsubscribe();

解决方案的另一部分涉及在我的***组件 AppComponent 中订阅 AngularFire auth observable。如果通过身份验证,它会重定向到一个路由;如果没有,它会重定向到另一个路由:

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

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

【问题讨论】:

【参考方案1】:

你有点搞砸了。您同时使用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();

【讨论】:

啊,软糖!我阅读并重新阅读了这个问题的文字,但错过了这个代码错误。我正在从更复杂的代码中提取它,试图将其提炼成一种显示问题本质的形式。但是我的翻译不正确。我没有将订阅分配给属性。对不起,让我更新我的代码。 感谢您的回复,顺便说一句!我刚刚尝试了ngOnDestroy 方法。我将订阅分配给组件对象属性,然后按照您的建议使用它取消订阅,但我仍然收到权限被拒绝错误。似乎使用this.auth.logout() 进行身份验证的行为不会触发我的组件上的ngOnDestroy 回调。 啊,ngOnDestroy 确实是解决方案的一部分。谢谢。

以上是关于与订阅的 observable 相关的注销权限错误的主要内容,如果未能解决你的问题,请参考以下文章

观察者模式(Observer Pattern)

RxJava Observer与Subscriber的关系

订阅 behviorSubject 中的 observable:出现错误

权限模块_分配权限_实现分配权限(登录与注销)的基本功能

为啥数组的 Observable 和订阅者不起作用?

Angular RxJS Observable:takeUntil 与使用订阅取消订阅 [关闭]