8

我有一个订阅流的 Web 组件。

由于每次显示 Web 组件时都会重新创建它,因此我必须清理订阅者并重做它。

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

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

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

我需要的是缓冲。注册监听器时,需要立即缓冲和发送事件。根据文档,在注册监听器之前会发生缓冲:

控制器将缓冲所有传入事件,直到订阅者注册为止。

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

似乎缓冲只发生在最初,即使所有听众都走了,也不会在以后发生。

所以问题是:在这种听众可能会来回走动的情况下,我该如何缓冲?

4

1 回答 1

11

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

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

一种方法(当然有很多方法)是为每个订阅者创建一个新的 Stream (就像 html-events 一样),它会暂停原始流。

origin的是原来的Stream。然后实现一个streamgetter,它返回一个链接到的新 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;
}

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

于 2013-05-01T23:38:02.267 回答