2017-05-31 60 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