2017-05-31 61 views
2

我按照我的角组件的清理模式,看起来像这样:我是否需要填写一个主题才能被垃圾收集?

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?

+1

即使你没有直接在主体上调用'complete()',你也可以用'takeUntil'操作符完成链,它会发送'complete'信号并使每个操作符递归地取消订阅。因此,“完全”信号是来自主体还是来自更远的链路,无关紧要。 – martin

+0

@马丁我认为你的回答是不正确的。对我来说,takeUntil将完成您应用takeUntil的流。不是使用takeUntil的人。看看大理石图:http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-takeUntil注意,当发射'z'时,最终流将关闭,但是包含'z'的流保持打开状态。所以肖恩,是的,你需要打电话给下一个,也是完整的。 – Maxime

+0

虽然我非常肯定它会在删除父类的引用时得到GC'd。这种模式对我来说似乎很可疑,为什么你不只是在关闭所有流时跟踪订阅并调用'unsubscribe'呢? – paulpdaniels

回答

2

如果你看看源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

+0

嗨@cartant,谢谢你的回答。就我所知,在'takeUntil'中有'Subject'作为观察者/订阅者参考吗?我假设不,因为该主题一旦发布就被取消订阅,但我只是想确认一下。 –

+1

'takeUntil'中的用法很好,因为主题对观察者的引用将通过'takeUntil'启动的取消订阅删除。观察者的参考可能会阻止收集主题 - 这取决于观察者的参考依据 - 但这是一个单独的问题,与主题是否调用“complete”无关。 – cartant