我有一个订阅流的网络组件。
由于每次显示Web组件时都会重新创建,我必须清理用户并重做它。
现在我正在将所有订阅者添加到列表中并使用removed()
生命周期方法:
subscriptions.forEach((sub) => sub.cancel());
现在,问题是:当没有显示Web组件时,没有人收听流。问题是当组件未显示时,组件缺少数据/事件。
我需要的是缓冲。在注册监听器时,需要缓冲事件并立即发送事件。 According to the documentation,缓冲发生直到监听者注册:
控制器将缓冲所有传入的事件,直到用户注册为止。
这样可行,但问题是侦听器会在某个时刻删除,并且重新注册,并且看起来这不会触发缓冲。
看起来缓冲只是最初发生,即使所有听众都已消失,也不会在以后发生。
所以问题是:如何在这种情况下缓冲,在这种情况下,听众可能会一去不复返?
答案 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;
}
如果您需要立即缓冲事件,则需要立即开始订阅,而不是像示例代码那样懒惰。