2014-12-23 5 views
1

안녕하세요!다트 스트림 구독 취소

저는 Dart에서 스트림의 동작을 이해하려고합니다.

: 우리는 Publisher

class Publisher { 

    StreamController<String> _publishCtrl = new StreamController<String>(); 
    Stream<String> onPublish; 

    Publisher() { 
     onPublish = _publishCtrl.stream.asBroadcastStream(); 
    } 

    void publish(String s) { 
     _publishCtrl.add(s); 
    } 
} 
  • 그리고

    class Reader { 
        String name; 
        Reader(this.name); 
        read(String s) { 
         print("My name is $name. I read string '$s'"); 
        } 
    } 
    
  • Reader 그리고 간단한 함수 main()

    1. :
      여기 은 간단한 예입니다 코드의 결과

    나는 독자 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(); 
          } 
         } 
        } 
    

    이 코드를 실행하면 콘솔 것이다 들만 게시물 : 나는 3 메시지가 있어야한다고 생각

    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

    동기화 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 루프가 완료된 후에 만 ​​리스너에게 전송된다는 것입니다. 따라서 첫 번째 항목이 'John'에 도착하기 전에 구독이 이미 취소되었습니다. 나는 나의 대답을 업데이트했다. –