在非组件/指令类中取消订阅 Observable

Posted

技术标签:

【中文标题】在非组件/指令类中取消订阅 Observable【英文标题】:Unsubscribing from Observable in a non-Component/Directive class 【发布时间】:2018-03-07 22:49:22 【问题描述】:

我已经阅读了大量关于在 Angular 中取消订阅 Observables 的帖子,所有帖子都提到仅在组件/指令中需要这样做。

所以我的问题是:

我们是否需要取消订阅非组件/指令类中的Observables,例如在包含订阅Observables 的服务或基本上任何其他类中?

【问题讨论】:

【参考方案1】:

我认为说明为什么退订很重要很重要。从来没有必要从流中取消订阅,但可以提高性能,并且在某些情况下,取消订阅作为功能的一部分很重要。

同样重要的是,取消订阅是消费者的责任。流“强制”消费者取消订阅的唯一方法是完成或出错。

在 Angular 服务中,如果您最终订阅了流,那么取消订阅是一种很好的做法,除非您有充分的理由继续收听。这是一个(人为的)示例:

import  Injectable  from '@angular/core';
import  Observable  from 'rxjs';

@Injectable()
export class MyService 
  constructor( private session: Session )  

  isLoggedIn(): Observable<boolean> 

    return Observable.create( observer => 
      const innerSubscription = this.session.subscribe( session => 
        if ( session.user.isLoggedIn ) 
          observer.next( true );
        
        observer.next( false );
      );

      return function unsubscribe() 
        innerSubscription.unsubscribe(); // this "cleans up" our subscription.
      ;
    );

  

还有其他更好的方法来编写此代码,这只是一个示例。所以在这种情况下,我们有一个订阅会话的非组件/指令。每次会话更改时,我们都会查看用户是否登录并通知我们的侦听器是否登录。如果每个人都取消订阅 us,除非我们(服务)明确取消订阅,否则我们仍会收听 this.session

【讨论】:

【参考方案2】:

您取消订阅组件是因为当您从 DOM 中删除它们时(例如使用 *ngIf 或其他),RxJS 链将保存对您在其中创建的观察者的引用。从而引入内存泄漏。

一般而言,您不必取消订阅服务,因为它们存在于您的应用程序的整个生命周期中。

但是,在 Angular 中,您可以创建一个组件,例如,仅向其后代提供不同的服务实例(这意味着您的应用程序中可能有多个相同服务类的实例)。在这种情况下,您应该手动取消订阅(可能在销毁定义它们的组件时)。

【讨论】:

因此,简而言之,我们可以设置一条规则:在 任何 种情况下,只要订阅的寿命应该短于 infinite @987654322,我们就必须取消订阅@。组件/指令中的订阅只是最常见的情况。是真的吗? @AlexanderAbakumov 是的,这基本上是我遵循的规则。 通常最好在服务的 ngOnDestroy 中手动取消订阅。如果服务由一个组件提供,然后被销毁(没有其他组件引用该服务,则该服务将被销毁,然后将调用其 on destroy 函数。 另外,对于在应用程序的生命周期内从未销毁的组件/服务,请注意单元测试的情况,这些组件可能会被销毁。在这种情况下,您要么仍然需要在组件/服务中取消订阅,要么需要在测试运行器的测试后挂钩中清理这些订阅。

以上是关于在非组件/指令类中取消订阅 Observable的主要内容,如果未能解决你的问题,请参考以下文章

京东小组件怎么取消

如何取消订阅角度组件中的多个可观察对象?

我应该取消订阅根 Angular 组件中的 observables 吗?

订阅/取消订阅 VS 创建/TakeUntil?

组件 ngOnInit 中的 Angular 订阅

在 Context.Consumer 创建的 useEffect 清理函数中取消所有订阅