rxjs 5 publishReplay refCount

10

Ich kann nicht herausfinden, wie publishReplay().refCount() funktioniert.

Zum Beispiel ( Ссылка ):

%Vor%

ergibt folgendes Ergebnis:

  

call observerA: 5

     

observerB: 5 call observerB: 5

     

observerC: 5 observerC: 5 call observerC: 5

     

BeobachterD: 5 BeobachterD: 5 BeobachterD: 5 Anruf BeobachterD: 5

1) Warum werden observerB, C und D mehrmals aufgerufen?

2) Warum wird "call" auf jeder Zeile und nicht am Anfang der Zeile gedruckt?

Auch wenn ich publishReplay(1).refCount() aufrufe, ruft es die Observer B, C und D jeweils zweimal auf.

Was ich erwarte ist, dass jeder neue Beobachter den Wert 5 genau einmal erhält und "call" nur einmal gedruckt wird.

    
Oleg Gello 12.02.2017, 15:57
quelle

3 Antworten

14

publishReplay(x).refCount() kombiniert macht Folgendes:

  • Erzeugt eine ReplaySubject , die bis zu x Emissionen wiedergibt. Wenn x nicht definiert ist, wird der gesamte Stream wiederholt.
  • Es macht diese ReplaySubject multicast-kompatibel mit einem refCount () -Operator. Dies führt dazu, dass gleichzeitige Abonnements die gleichen Emissionen erhalten.

Ihr Beispiel enthält ein paar Probleme, die verdeutlichen, wie alles zusammen funktioniert. Siehe das folgende überarbeitete Snippet:

%Vor% %Vor%

Beim Ausführen dieses Snippets können wir klar sehen, dass es keine doppelten Werte für Beobachter D ausgibt, es erzeugt tatsächlich neue Emissionen für jedes Abonnement. Wie kommt es?

Jedes Abonnement wird abbestellt, bevor das nächste Abonnement stattfindet. Dies führt dazu, dass refCount auf Null zurückgeht und kein Multicasting durchgeführt wird.

Das Problem liegt darin, dass der realSource -Stream nicht abgeschlossen wird. Da es sich nicht um Multicasting handelt, erhält der nächste Abonnent eine neue Instanz von realSource durch das ReplaySubject und die neuen Emissionen werden mit den zuvor bereits emittierten Emissionen vorangestellt.

Um zu verhindern, dass Ihr Stream die teure HTTP-Anfrage mehrmals aufruft, müssen Sie den Stream vervollständigen, damit das publishReplay weiß, dass es sich nicht erneut abonnieren muss.

    
Mark van Straten 13.02.2017, 08:36
quelle
4

Dies passiert, weil Sie publishReplay() verwenden. Es erstellt intern eine Instanz von ReplaySubject , die alle durchlaufenden Werte speichert.

Da Sie Observable.create verwenden, wo Sie einen einzelnen Wert ausgeben, hängen Sie bei jedem Aufruf von source.subscribe(...) einen Wert an den Puffer in ReplaySubject an.

Sie erhalten call nicht am Anfang jeder Zeile, weil es der ReplaySubject ist, der seinen Puffer zuerst ausgibt, wenn Sie ihn abonnieren und dann seine Quelle selbst abonniert:

Details zur Implementierung finden Sie unter:

Gleiches gilt für die Verwendung von publishReplay(1) . Zuerst gibt es den gepufferten Gegenstand von ReplaySubject und dann noch einen Gegenstand von observer.next(5);

aus     
martin 13.02.2017 08:26
quelle
4

Im Allgemeinen: refCount bedeutet, dass der Stream heiß / geteilt ist, solange mindestens ein Teilnehmer vorhanden ist - er wird jedoch zurückgesetzt / kalt, wenn keine Teilnehmer vorhanden sind.

Dies bedeutet, wenn Sie absolut sicher sein wollen, dass nichts mehr als einmal ausgeführt wird, sollten Sie nicht refCount() , sondern einfach connect den Stream verwenden, um es heiß zu setzen.

Als zusätzliche Anmerkung: Wenn Sie observer.complete() nach observer.next(5); hinzufügen, erhalten Sie auch das erwartete Ergebnis.

Hinweis: Müssen Sie wirklich Ihre eigene benutzerdefinierte Obervable hier erstellen? In 95% der Fälle reichen die vorhandenen Betreiber für den gegebenen Anwendungsfall aus.

    
olsn 13.02.2017 08:26
quelle

Tags und Links