2016-07-28 68 views
9

我想可能會繼續訂閱觀察者並忘記取消訂閱。我懷疑這是發生在我的應用程序中。觀察者是否擁有一個可以讓我計算用戶數量的屬性?在angular2中,是否有可能獲得可觀察用戶的計數?

+1

我認爲最接近你可以得到的是使用.refCount()。 https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/refcount.md –

+0

我根據你的描述回答了你希望有方法不要忘記取消訂閱,因爲我覺得它是你問題的核心。當然有一些方法可以編寫一個實際上有助於計算的運算符,但由於不同運營商可能在流的不同點上訂閱的方式等因素,這會非常複雜。希望我的回答能夠爲您提供所需的工具,而無需進入可觀察的用戶數量的元信息。 –

回答

8

雖然絕對有可能忘記取消訂閱,並且泄漏的後果從永無止境的測試運行者到內存泄漏,但angular2擁有一些工具和通用模式來管理其生命週期。

angular2提供了一種不會忘記的簡單方法。在模板中使用最簡單的方法是簡單地使用異步管道,該管道將自動爲您訂閱和取消訂閱。

否則,當您使用.subscribe()方法時,它會返回訂閱。通常的做法是在構造函數中捕獲注入的依賴關係,對ngOnInit中的組件進行必要的訂閱,並取消訂閱ngOnDestroy

有時候,你會訂閱多個觀察對象。 RxJS將類Rx.Subscription提供給組訂閱。它可以通過以下方式使用:

const incomeSubscription = income$.subscribe(x => console.log(x)); 
const expensesSubscription = expenses$.subscribe(x => console.log(x)); 

const subscription = new Rx.Subscription(); 
subscription.add(incomeSubscription); 
subscription.add(expensesSubscription); 

現在呼籲subscription.unsubscribe()將取消任何訂閱仍然有效。

最後,理解RxJS流默認是單播是​​非常重要的(不像承諾總是緩存結果並且只是多播)。這意味着在實踐中,每個訂閱實際上成爲一個新的rx流。在例如Http.get()等「冷」可觀察的情況下,每個訂閱實際上將從頭開始生成數據。因此,在Http.get()提到的情況下,您將爲每個訂閱(或在模板中使用管道異步的實例)進行HTTP調用。

這意味着它是很好的做法:

  • 僅使用異步管道在容器風格組件,以及有什麼都不知道RxJS的啞 表象成分。這有助於 僅在容器級別

  • 訂閱如果用戶之間共享數據使用像.refCount運營商() 在其他一些情況下,或主題。這使得流播 和用戶分享,而不是每個人都有相同的流自己的

+1

使用角度v4,已經成爲使用'|的好實踐async'結合'as secondaryName'(stream $ | async as streamData),所以在容器組件中,如果多次使用observable的值,則不會多次訂閱observable。 –

+0

行爲(可能的內存泄漏是由過多的訂閱引起的)對於Angular 5.x.x來說是否一樣? –

0

我有這個問題,我通過建立訂閱數組解決了這個問題:每次

import { Subscription } from 'rxjs/Rx'; 

private subValueChanges: Array<Subscription>; 

然後我訂閱,推入陣列:

this.subValueChanges.push(
    this.someControl.valueChanges 
     .debounceTime(1000) 
     .distinctUntilChanged() 
     .takeUntil(this.destroyValueChanges$) 
     .subscribe (newValue => {...} 
); 

然後你知道數組的長度是'someControl'有多少用戶。

我不推薦它作爲解決方案,但有邊緣情況下,這可能是有用的(我有一個)。

另外有趣的是訂閱有一個標誌「關閉」屬性,你可以檢查 - 如果它關閉,例如,你可以從數組中刪除它。或者,當您首次訂閱時,請設置onunsubscribe事件以從陣列中刪除該特定訂戶。無論哪種方式,那麼你的數組將只包含活躍的監聽器 - 所以它的長度總是告訴你他們有多少人在那裏! :)