我正在寻找一种基于测试方法从广播流中派生新Streams的方法,但这不会导致为每个订阅调用测试方法:
流在哪里(功能bool测试(T事件))
从此流创建一个丢弃某些数据事件的新流。
新流发送与此流相同的错误和完成事件,但它仅发送满足测试的数据事件。
如果此流是,则返回的流是广播流。如果多次收听广播流,则每个订阅都会 单独进行测试。
有没有其他方法可以从源广播流中派生子广播流,而不会为每个订阅调用测试方法?
答案 0 :(得分:2)
我无法在核心异步API中找到一个简单的解决方案,但我发现如果您将流转发到另一个流,以进行每种类型的测试,性能节省是巨大的,this是我的使用这种流转发技术的类,它比下面的第二个原始版本执行得更好,这将对每个发出的对象的每个订阅强制执行类型检查:
/// A mixin class to enable any class to act as a generic emitter of objects.
class Emitter {
final StreamController _controller = new StreamController.broadcast();
final Map<Type, Stream> _streamCache = new Map<Type, Stream>();
/**
* Emit an object.
*
* emit(new Foo());
*
* Will send the new Foo object down the stream returned by `on(Foo)`.
*/
void emit(obj) => _controller.add(obj);
/// Get the stream of [type].
Stream on(Type type){
var stream = _streamCache[type];
if(stream == null){
StreamController controller = new StreamController.broadcast();
_streamCache[type] = stream = type == All? _controller.stream: controller.stream;
if(type != All){
_controller.stream.where(_typeMatcher(type)).listen(controller.add, onError: controller.addError, onDone: controller.close);
}
}
return stream;
}
}
这是on方法的旧的非常慢的实现:
/// Get the stream of [type].
Stream on(Type type) => type == All? _controller.stream: _controller.stream.where(_typeMatcher(type));
对于某些性能数字,如果向200个侦听器发出100000个对象,则高性能在6.6秒内运行,慢速版本在20.2秒内运行。
答案 1 :(得分:2)
Quiver的StreamRouter
可能不是您想要的,但它确实只对每个事件执行一次测试,而不是每个事件每次执行一次。它与您的Emitter
有些相似,只是事件只能流入一个派生流。
var router = new StreamRouter(new Stream.fromIterable(range(0, 10)));
var odds = router.route((i) => i % 2 == 1);
odds.listen((i) { print(i); });
odds.listen((i) { print("$i is odd"); });
传递给route
的谓词每个事件只调用一次。
这是文档:
此外,并非您的Emmiter
不需要缓存Streams以获得仅调用一次测试的行为,而是来自手动创建控制器并调用add()
。所以你可以得到同样的东西:
/// Get the stream of [type].
Stream on(Stream source, Type type) {
var controller = new StreamController();
controller.addStream(source.where(_typeMatcher(type)));
return controller.stream;
}