2014-12-23 2 views
1

Hello!Dart Streams отписаться

Я пытаюсь понять работу потоков в Дарт.
Вот простой пример:

  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"); 
        } 
    } 
    

В результате кода я получаю 5 консольных сообщений от читателя John и 5 сообщений от читателя Smith.

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 сообщения от читателя Smith.

Скажите, пожалуйста, если все, что я знаю правильно? Если нет, помогите мне, пожалуйста, понять, почему это происходит.

спасибо.

ответ

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; 
    } 
+0

Спасибо за ваш ответ. Я добавил в конец кода вопроса, который вы предлагаете, но результат не изменился. В результате программы я получаю информацию о том, какие сообщения принимаются только читателю ** John **. Но мне кажется, что первые 3 сообщения должны получить и ** Smith ** –

+0

Я пропустил, что вы уже сохранили 'StreamSubscription'. Тогда мой ответ недействителен. Это еще один способ сохранить и отменить набор «StreamSubscriptions». –

+0

Я предполагаю, что проблема заключается в том, что ваш поток является асинхронным, и опубликованные элементы передаются только слушателям после завершения цикла for. Таким образом, подписка была отменена до того, как первый элемент появился для «Джона». Я обновил свой ответ. –

Смежные вопросы