如何缓冲流事件?

时间:2013-05-01 18:45:11

标签: dart

我有一个订阅流的网络组件。

由于每次显示Web组件时都会重新创建,我必须清理用户并重做它。

现在我正在将所有订阅者添加到列表中并使用removed()生命周期方法:

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

现在,问题是:当没有显示Web组件时,没有人收听流。问题是当组件未显示时,组件缺少数据/事件。

我需要的是缓冲。在注册监听器时,需要缓冲事件并立即发送事件。 According to the documentation,缓冲发生直到监听者注册:

  

控制器将缓冲所有传入的事件,直到用户注册为止。

这样可行,但问题是侦听器会在某个时刻删除,并且重新注册,并且看起来这不会触发缓冲。

看起来缓冲只是最初发生,即使所有听众都已消失,也不会在以后发生。

所以问题是:如何在这种情况下缓冲,在这种情况下,听众可能会一去不复返?

1 个答案:

答案 0 :(得分:11)

注意:通常您不能重新订阅已关闭的Stream。这似乎是我们忘记解决的错误。

我对网络组件不熟悉,但我希望我能通过以下建议解决您的问题。

一种方式(当然有许多方法)是为每个订阅者创建一个新流(如html-events),暂停原始流。

origin是原始流。然后实现一个stream getter,它返回一个链接到origin的新Stream:

未经测试的代码。

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;
}

如果您需要立即缓冲事件,则需要立即开始订阅,而不是像示例代码那样懒惰。