无论如何都要导出一个不会每次都检查测试方法的新流吗?

时间:2014-10-30 18:57:57

标签: dart

我正在寻找一种基于测试方法从广播流中派生新Streams的方法,但这不会导致为每个订阅调用测试方法:

  

流在哪里(功能bool测试(T事件))

     

从此流创建一个丢弃某些数据事件的新流。

     

新流发送与此流相同的错误和完成事件,但它仅发送满足测试的数据事件。

     

如果此流是,则返回的流是广播流。如果多次收听广播流,则每个订阅都会   单独进行测试。

有没有其他方法可以从源广播流中派生子广播流,而不会为每个订阅调用测试方法?

2 个答案:

答案 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的谓词每个事件只调用一次。

这是文档:

http://www.dartdocs.org/documentation/quiver/0.19.0-dev.3/index.html#quiver/quiver-async.StreamRouter

此外,并非您的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;
}