Dart Streams取消订阅

时间:2014-12-23 14:19:45

标签: dart

您好!

我试图了解Dart中溪流的运作方式 这是一个简单的例子:

  1. 我们有Publisher

    class Publisher {
    
        StreamController<String> _publishCtrl = new StreamController<String>();
        Stream<String> onPublish;
    
        Publisher() {
            onPublish = _publishCtrl.stream.asBroadcastStream();
        }
    
        void publish(String s) {
            _publishCtrl.add(s);
        }
    }
    
  2. Reader

    class Reader {
        String name;
        Reader(this.name);
        read(String s) {
            print("My name is $name. I read string '$s'");
        }
    }
    
  3. 简单函数main()

    main() {
        Publisher publisher = new Publisher();
    
        Reader john = new Reader('John');
        Reader smith = new Reader('Smith');
    
        publisher.onPublish.listen(john.read);
        publisher.onPublish.listen(smith.read);
    
        for (var i = 0; i < 5; i++) {
            publisher.publish("Test message $i");
        }
    }
    
  4. 作为代码的结果,我从阅读器John获得5条控制台消息,从阅读器Smith获得5条消息。

    My name is John. I read string 'Test message 0'
    My name is Smith. I read string 'Test message 0'
    My name is John. I read string 'Test message 1'
    My name is Smith. I read string 'Test message 1'
    My name is John. I read string 'Test message 2'
    My name is Smith. I read string 'Test message 2'
    My name is John. I read string 'Test message 3'
    My name is Smith. I read string 'Test message 3'
    My name is John. I read string 'Test message 4'
    My name is Smith. I read string 'Test message 4'
    

    一切正常。但是,如果我尝试更改周期for,那么在2步读取Smith阻止接收消息之后,该消息将只接收读者John。 以下是更改函数main ()的示例:

        main() {
            Publisher publisher = new Publisher();
    
            Reader john = new Reader('John');
            Reader smith = new Reader('Smith');
    
            publisher.onPublish.listen(john.read);
            var smithSub = publisher.onPublish.listen(smith.read);
    
            for (var i = 0; i < 5; i++) {
                publisher.publish("Test message $i");
    
                if (i > 2) {
                    smithSub.cancel();
                }
            }
        }
    

    如果您运行此代码,则控制台只会通过 John

    发布
    My name is John. I read string 'Test message 0'
    My name is John. I read string 'Test message 1'
    My name is John. I read string 'Test message 2'
    My name is John. I read string 'Test message 3'
    My name is John. I read string 'Test message 4'
    

    但我认为应该有来自读者史密斯的3条消息。

    如果我知道的话,请告诉我吗?如果没有,请帮助我,理解为什么会发生这种情况。

    非常感谢。

1 个答案:

答案 0 :(得分:3)

创建同步StreamController

StreamController<String> _publishCtrl = new StreamController<String>(sync: true);

或允许控制器在发送新项目之前处理这些项目

  int i = 0;
  Future.doWhile(() {
    i++;

    publisher.publish("Test message $i");

    if (i > 2) {
      subscriptions
        ..forEach((s) => s.cancel())
        ..clear();
    }
    return i < 5;
  }