【问题标题】:How to unsubscribe multiple observables in angular component?如何取消订阅角度组件中的多个可观察对象?
【发布时间】:2019-08-20 09:50:12
【问题描述】:

取消订阅多个角度观察的最佳策略是什么?需要明确的是,当应用程序不大并且不需要像 ngrx 这样的解决方案时,我会使用这种方法,在这种情况下会是 过度工程.

目前我使用订阅实例来添加所有订阅,然后当组件被销毁时我调用取消订阅方法。但我也看到了使用 rxjs 中的 takeUntil 的替代方法。

export class MyComponent implements OnInit, OnDestroy {

  $firstObservable: Observable<number> = timer(0, 1000);
  $secondObservable: Observable<number> = timer(0, 1000);

  private _subscriptions = new Subscription();

  constructor() { }

  ngOnDestroy(): void {
    this._subscriptions .unsubscribe();
  }

  ngOnInit(): void {
    this._subscriptions .add(
      this.$firstObservable.subscribe(console.log));

    this._subscriptions .add(
      this.$secondObservable.subscribe(console.log));
  }

}

最好的解决方案是什么?

【问题讨论】:

  • 您可以将所有这些订阅合并到一个.subscribe
  • takeUntil 目前被认为是最佳实践。
  • 使用takeUntil 是最简单的方法。顺便说一句,您可以链接 this._subscriptions.add().add().add() 调用,这样会更短一些。

标签: angular rxjs observable


【解决方案1】:

我建议你使用takeUntil() pipeable 运算符:https://www.learnrxjs.io/operators/filtering/takeuntil.html

这样,您创建了一个Subject,它将在ngOnDestroy 上发出值并一次取消订阅多个订阅

 unsubscribeSignal: Subject<void> = new Subject();

 $firstObservable: Observable<number> = timer(0, 1000);
 $secondObservable: Observable<number> = timer(0, 1000);

 ngOnInit() {

    this.$firstObservable
    .pipe(
       takeUntil(this.unsubscribeSignal.asObservable()),
    )
    .subscribe(result => {});

    this.$secondObservable
    .pipe(
       takeUntil(this.unsubscribeSignal.asObservable()),
    )
    .subscribe(result => {});

  }

  ngOnDestroy(){
    this.unsubscribeSignal.next();
    // Don't forget to unsubscribe from subject itself
    this.unsubscribeSignal.unsubscribe();
  }

【讨论】:

  • 您可以在我在上一个答案中分享的链接中看到。使用 takeUntil 运算符时必须小心。 “我们不应该忘记 takeUntil 运算符必须是管道中的最后一个运算符(通常)以防止后续运算符返回可能阻止清理的其他可观察对象的情况。- by Brian Love”。
【解决方案2】:

我很失望人们甚至没有提到async 管道。

它非常强大,让您无需担心订阅问题并使用推送检测策略。

要使用它,只需从您的 TS 中删除订阅,并将值分配给您的变量,这些变量将被键入为 observables。

只看代码精简和简洁(不知道是不是一个词,但有点不在意)

export class MyComponent {
  firstObservable$: Observable<number> = timer(0, 1000);
  secondObservable$: Observable<number> = timer(0, 1000);

  combination$ = combineLatest(this.firstObservable$, this.secondObservable$)
    .pipe(tap(() => console.log()));
}

在你的 HTML 中

<ng-container *ngIf="combination$ | async">
  Observables are being observed.
</ng-container>

(尽管它不适合您的问题示例,但您已经可以看到它是如何更清洁和更简单的)

最好的一点是,您不必再担心内存泄漏。 Angular 负责所有订阅,让您只关心您的代码(这是一个好的框架应该做的)。

【讨论】:

  • 是的,异步管道非常强大。但有些情况需要手动订阅。
  • @RenatoSantos 然后提供这些案例,而不是这样的例子!
  • @trichetriche 我刚刚发布了一个答案,其中我指的是显示所有场景的帖子。
【解决方案3】:

最简单的方法是存储subscribtion 对象并在ngDestory 上调用取消订阅方法。

export class MyComponent implements OnInit, OnDestroy {

  $firstObservable: Observable<number> = timer(0, 1000);
  $secondObservable: Observable<number> = timer(0, 1000);
   
  private _subscriptions :any[] = [];

  constructor() { }

  ngOnDestroy(): void {
    this._subscriptions .unsubscribe();
  }

  ngOnInit(): void {
    this._subscriptions .push(
      this.$firstObservable.subscribe(console.log)
    );

    this._subscriptions .push(
      this.$secondObservable.subscribe(console.log)
    );
  }

   ngOnDestroy(){
    this._subscriptions.forEach(sub => sub.unsubscribe()) ; // ?‍♂️?‍♂️
  }

}

【讨论】:

    【解决方案4】:

    Subscribe 类有一个 add 方法,可以将多个订阅合二为一,然后可以同时为 unsubscribed

    subscription1 = observable.subscribe(
        // next, err, complete etc
    );
    
    subscription2 = observable.subscribe(
        // next, err, complete etc
    );
    

    添加多个订阅

    subscription1.add(subscription2);
    

    一次性取消所有订阅。

    subscription1.unsubscribe();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      • 2021-11-26
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      相关资源
      最近更新 更多