【问题标题】:Angular - what is the preferred way to terminate Observables?Angular - 终止 Observables 的首选方法是什么?
【发布时间】:2018-01-02 04:31:37
【问题描述】:

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

unsubscribe() 方法

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,您正在这样做。我唯一要补充的是检查这些值是否“真实”,即不为空或未定义,否则尝试调用unsubscribe() 时会出错。
  • 请注意,您通常不需要终止常见的可观察对象,例如示例中的路由器参数。 Angular 会自动终止它们。请参阅文档这部分底部附近的注释:angular.io/guide/…

标签: angular rxjs rxjs5 angular2-observables unsubscribe


【解决方案1】:

这两种方法都是正确的,即使它们不等价。

在我看来(和经验)使用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. 您可以将Subscriptions 组合成一个并一次性取消订阅:

    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
    

【讨论】:

  • 您的示例运行良好。对我来说,短版本 subscription = Observable...subscribe(...).add(sub1).add(sub2); subscription.unsubscribe(); 仅取消订阅最新订阅 sub2 对我来说并不明显,因为 subscription.add(...) 方法返回其参数。
【解决方案2】:

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

 accountSubscriptionObj : Subscription;

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多