Angular - 终止 Observables 的首选方式是什么?

Angular - what is the preferred way to terminate Observables?

根据我对 Angular 和 RxJs 的理解,有两种方法可以终止 Observable。您可以从他们那里 unsubscribe() 或使用 takeUntil()complete()。下面是每种方法的示例(伪代码)。

取消订阅() 方法

private _id: number;
private _subscriptions: Subscription[] = [];

constructor(private _route: ActivatedRoute) {
    this._getId();
}

public ngOnDestroy(): void {
    this._subscriptions.forEach(
        subscription => subscription.unsubscribe()
    );
}

private _getId(): void {
    this._subscriptions.push(
        this._route.params.subscribe(params => this._id = +params['id'])
    );
}

takeUntil() 和 complete() 方法

private _id: number;
private _ngUnsubscribe: Subject<void> = new Subject<void>();

constructor(private _route: ActivatedRoute) {
    this._getId();
}

public ngOnDestroy(): void {
    this._ngUnsubscribe.next();
    this._ngUnsubscribe.complete();
}

private _getId(): void {
    this._route.params.takeUntil(this._ngUnsubscribe).subscribe(
        params => this._id = +params['id']
    );
}

在Angular中,有没有更好的方法来终止 Observables?

我这样做的方法是首先检查 ngOnDestroy,如果 Observable 存在。如果是,则取消订阅。以下是我的应用程序中的代码片段。

 accountSubscriptionObj : Subscription;

 ngOnDestroy() {
    if (this.accountSubscriptionObj) {
      this.accountSubscriptionObj.unsubscribe();
    }
  }

与此同时,您不需要取消订阅异步管道,@HostListener, 有限可观察。 当组件被销毁时,异步管道会自动取消订阅以避免潜在的内存泄漏。当你有一个有限序列时,通常你不需要取消订阅,例如当使用 HTTP 服务或定时器可观察时。更多参考 read here.

这两种方法都是正确的,尽管它们并不等同。

根据我的观点(和经验),使用 unsubscribe() 通常更有意义,并且对于其他没有丰富 RxJS 经验的开发人员来说更明显。

RxJS 5 (https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87) 的首席开发人员推荐使用 takeUntil(),有时比处理多个订阅对象更容易使用。例如,如果您使用 partition() 运算符将一个流分成两个,则仅使用 takeUntil(...).partition(...).

会更容易

但是有两件重要的事情:

  1. 这两个不一样。如果你使用 takeUntil() 你正在完成 Observable 链,这意味着所有完整的句柄都被调用,然后是拆卸函数。另一方面,当您调用 unsubscribe() 时,只会调用拆卸函数(包括 finally() 等运算符)。

    这就是为什么我认为使用 unsubscribe() 更有意义。使用 takeUntil() 你可能有一个 complete 处理程序被调用,即使你只是想取消订阅(更不用说这会触发使用 complete 信号的运算符,例如 repeat()可能会再次重新订阅)。您想要取消订阅的事实并不意味着源 Observable 已完成。您只是不再关心它的值,所以在这种情况下使用 unsubscribe() 可能更好。

    然而,实际上,您是完成链还是取消订阅通常并不重要。

  2. 您可以将 Subscription 组合成一个并立即取消订阅:

    const subscription = new Subscription();
    
    const sub1 = Observable...subscribe(...);
    const sub2 = Observable...subscribe(...);
    const sub3 = Observable...subscribe(...);
    
    subscription.add(sub1).add(sub2).add(sub3);
    
    ...
    
    subscription.unsubscribe(); // unsubscribes all of them