【问题标题】:Should I unsubscribe from Cold Observable?我应该退订 Cold Observable 吗?
【发布时间】:2017-06-19 10:12:16
【问题描述】:

我知道最好取消订阅 Observable 以防止内存泄漏

但如果它是Cold Observable,我是否也应该取消订阅它?

例如Http.get()返回的一个

【问题讨论】:

  • 您可以使用.take(1) 强制Obs 终止并避免内存泄漏。所以:http.get(...).take(1)
  • @AngularFrance 如果你查看源代码github.com/ReactiveX/rxjs/blob/master/src/operator/take.ts 你会看到 yes unsubscribe 被调用,但由于它的冷可观察然后完成也会被调用,所以没有必要说 take 1 if only 1 个将被退回
  • 我已经更新了我的答案:)
  • 冷的 observables 不必完成。编写一个永远不会发生的冷可观察对象是微不足道的。另见intervaltimer。订阅者会自动取消订阅完成或错误的 observables - 无论是热的还是冷的。否则,需要明确取消订阅。
  • @VolodymyrBilyachat。有趣,我不知道。

标签: angular rxjs


【解决方案1】:

你不需要这样做。 HTTP observable 在操作完成后立即调用完成。

从源代码sources 我可以看到unsubscribe 在错误和完成时被调用。

protected _error(err: any): void {
    this.destination.error(err);
    this.unsubscribe();
}

protected _complete(): void {
    this.destination.complete();
    this.unsubscribe();
}

我更进一步,做了一个小实验,添加了 unsubscribe 和超时

var subscription = this.http.get(`apiurl`)
            .subscribe(response => {
                setTimeout(function(){ 
                    debugger;
                    subscription.unsubscribe(); }, 30);
            });

如果我走进unsubscribe

 Subscriber.prototype.unsubscribe = function () {
        if (this.closed) { // this.closed is true
            return;
        }
        this.isStopped = true;
        _super.prototype.unsubscribe.call(this);
    };

然后是this.closed == true,这意味着unsubscribe之前被调用过。

所以是的,现在我可以肯定地说您不需要退订 :)

【讨论】:

    【解决方案2】:

    由于 Cold Observables 是有限的,您不必取消订阅。

    退订时间:

    • 无限 Obesrvables,例如。间隔()
    • 如果订阅(Subject、BehaviorSubject、ReplaySubject、AsyncSubject)

    在 ReplaySubject 的情况下,如果未提供缓存生命周期,则应取消订阅

    如果是 AsyncSubject,如果未完成,您应该取消订阅

    • Websocket 流
    • 抽象控制 ex。 valueChanges()
    • Renderer2.listen()
    • 事件流例如。 formEvent()
    • NgRx 商店

    在以下情况下不要退订:

    • 如果流结束自己前。 of('1','2')
    • Router 事件,Router 中的所有 Observable 都在自行退订
    • 异步管道
    • 有限可观察前。 http.get()
    • EventEmiter

    如果未完成或出错,则必须取消订阅。

    如果我错了或遗漏了什么,请告诉我。 谢谢;)

    【讨论】:

      【解决方案3】:

      就像其他编程语言一样,在 javascript 中释放已用内存绝对是最佳实践。

      由于您使用的是 Angular 2,因此您可以使用 ngOnDestroy 生命周期钩子来实现,因为当组件失去其作用域时会执行此方法。

      假设你使用下面的sn-p订阅一个数据

      subscription = this._http.getMethod('...')
                          .subscribe(response => this.responses = response,
                          error =>this.errorMessage =<any> error)
      

      您应该使用 import 语句从 angular/core 使用 importing OnDestroy 生命周期钩子。

      import { OnDestroy } from '@angular/core'
      

      在你的组件中实现 OnDestroy

      export class MyComponent implements onDestroy {
           .............
      
      
           ngOnDestroy() {
                this.subscription.unsubscribe();
           }
      
      }
      

      【讨论】:

      • 为什么?退订什么都不做
      • 我建议这是使用 ngOnDestroy 来消除所有内存泄漏的好习惯
      • 这不是一个好习惯,您建议添加 3 行代码,因为它们不是必需的。如果我有间隔或循环调用 http 你会建议创建数组和取消订阅怎么办?
      猜你喜欢
      • 1970-01-01
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多