【问题标题】:Do I need to complete a Subject for it to be garbage collected?我需要完成一个主题才能被垃圾收集吗?
【发布时间】:2017-05-31 16:15:49
【问题描述】:

我在我的 Angular 组件中遵循如下所示的清理模式:

class SomeComponent implements OnInit, OnDestroy {
    private destroy$ = new Subject();

    ngOnInit() {
        service.someStream().takeUntil(this.destroy$).subscribe(doSomething);
    }

    ngOnDestroy() {
        this.destroy$.next(true);
    }
}

这样做的好处是在组件被销毁时自动取消订阅。

我的问题是:对 destroy$ 的引用是否会因为我没有调用 this.destroy$.complete() 而无限期地存在,还是会在收集父类时被 GC 处理?

【问题讨论】:

  • 即使您没有直接在主题上调用complete(),您也可以使用takeUntil 运算符完成链,该运算符发送complete 信号并使每个运算符递归地取消订阅。因此,complete 信号是来自主题还是更下游的某个地方并不重要。
  • @martin 我认为您的回答不正确。对我来说,takeUntil 将完成您应用 takeUntil 的流。不是用于 takeUntil 的那个。看一下弹珠图:reactivex.io/rxjs/class/es6/… 请注意,当发出z 时,最终流是关闭的,但包含z 的流仍然是打开的。所以肖恩,是的,你需要调用下一个,也是完整的。
  • 虽然我很确定当对父类的引用被删除时它会被 GC 处理。这种模式对我来说似乎很可疑,为什么你不简单地跟踪订阅并在关闭所有流时调用unsubscribe
  • @paulpdaniels 如果您有多个订阅,则必须保留对每个订阅的引用并按顺序调用取消订阅。通过使用上面的模式,您可以拥有一个一次性取消订阅它们的主题。结果代码更少,可读性更高。
  • OP是关于垃圾收集subject,为什么cmets讨论如何垃圾收集subscriptions

标签: angular rxjs


【解决方案1】:

如果您查看Subject.complete 的来源,您会找到答案:

complete() {
  if (this.closed) {
    throw new ObjectUnsubscribedError();
  }
  this.isStopped = true;
  const { observers } = this;
  const len = observers.length;
  const copy = observers.slice();
  for (let i = 0; i < len; i++) {
    copy[i].complete();
  }
  this.observers.length = 0;
}

调用complete 会通知任何观察者,然后清除观察者数组。除非您的观察者/订阅者引用了Subject,否则complete 实现中不会影响Subject 是否可以被垃圾回收。

RxJS 向订阅者推送通知。订阅者不持有对可观察对象的引用;情况恰恰相反。因此,除非您通过闭包或其他机制显式创建了持有对 Subject 的引用的订阅者,否则无需调用 complete 进行垃圾收集。

【讨论】:

  • 嘿@cartant,谢谢你的回答。我很清楚,将我的Subject 放入takeUntil 是否算作具有参考的观察者/订阅者?我认为不会,因为该主题一旦发出就被取消订阅,但我只是想确定一下。
  • takeUntil 中的使用很好,因为主题对观察者的引用将通过takeUntil 发起的取消订阅删除。观察者的引用可能会阻止主题被收集 - 取决于引用观察者的内容 - 但这是一个单独的问题,与是否在主题上调用 complete 无关。
  • @cartant,那么这是预防措施,而不是必需品take-until-destroy.ts#L26,对吧? 我只是在研究和 OP 一样的东西,所以请不要认为这很烦人。
  • 所以,基本上调用 subject.complete() 会清除主题内部维护的观察者/订阅列表,它不会垃圾收集主题本身?
猜你喜欢
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 2019-01-14
  • 1970-01-01
相关资源
最近更新 更多