2013-05-01 54 views
8

我有一個訂閱流的Web組件。如何緩衝流事件?

由於每次顯示Web組件時都會重新創建Web組件,因此我必須清理訂戶並重做它。

現在我將所有用戶的列表,並在removed()生命週期的方法我在做:

subscriptions.forEach((sub) => sub.cancel()); 

現在的問題:當不顯示Web組件,有沒有一個聽流。問題在於組件在未顯示時缺少數據/事件。

我需要的是緩衝。偵聽器註冊時,事件需要緩衝並立即發送。 According to the documentation,緩衝發生,直到聽衆註冊:

控制器將緩衝所有傳入的事件,直到用戶註冊。

這工作,但問題是,聽者會在某個時刻去除重新登記,看來這不會觸發緩衝。

看起來,緩衝只發生在最初,即使所有的聽衆都不在,以後也不會發生。

所以問題是:如何緩衝這種情況下聽衆可能會消失又回來?

回答

11

注意:通常您不應該能夠重新訂閱已關閉的流。這似乎是我們忘記修復的錯誤。

我不熟悉web組件,但我希望我解決您的問題,並提出以下建議。

一種方法(當然也有很多)會爲每個用戶創建一個新的流(如html事件),以暫停原始流。

origin是原始流。然後實現一個stream獲取器,該獲取器返回鏈接到origin的新流:

未經測試的代碼。

Stream origin; 
var _subscription; 
final _listeners = new Set<StreamController>(); 

_addListener(controller) { 
    _listeners.add(controller); 
    if (_subscription == null) { 
    _subscription = origin.listen((event) { 
     // When we emit the event we want listeners to be able to unsubscribe 
     // or add new listeners. In order to avoid ConcurrentModificationErrors 
     // we need to make sure that the _listeners set is not modified while 
     // we are iterating over it with forEach. Here we just create a copy with 
     // toList(). 
     // Alternatively (more efficient) we could also queue subscription 
     // modification requests and do them after the forEach. 
     _listeners.toList().forEach((c) => c.add(event)); 
    }); 
    } 
    _subscription.resume(); // Just in case it was paused. 
} 
_removeListener(controller) { 
    _listeners.remove(controller); 
    if (_listeners.isEmpty) _subscription.pause(); 
} 

Stream get stream { 
    var controller; 
    controller = new StreamController(
     onListen:() => _addListener(controller), 
     onCancel:() => _removeListener(controller)); 
    return controller.stream; 
} 

如果您需要緩衝的事件立即就需要開始訂閱馬上而不是懶洋洋地在示例代碼。

+1

正是我想要的。謝謝!我想我會在'BufferedStreamController'(或其他)實現中包裝它,因爲我需要在幾個地方使用它。 – 2013-05-02 12:17:01

+1

編輯代碼:我忘記了同時修改。當一個事件發出時,我們希望聽衆能夠訂閱或取消訂閱。 – 2013-05-07 07:30:56