Heiße und kalte Observable: Gibt es „heiße“ und „kalte“ Operatoren?

Lesezeit: 10 Minuten

Heise und kalte Observable Gibt es „heise und „kalte Operatoren
Benutzer3743222

Ich habe die folgende SO-Frage überprüft: Was sind die heißen und kalten Observablen?

Zusammenfassen:

  • Ein Cold Observable gibt seine Werte aus, wenn es einen Beobachter hat, der sie konsumiert, dh die Folge der von Beobachtern empfangenen Werte ist unabhängig vom Zeitpunkt des Abonnements. Alle Beobachter verbrauchen dieselbe Folge von Werten.
  • Ein Hot Observable gibt Werte unabhängig von seinen Abonnements aus, dh die von Beobachtern empfangenen Werte sind eine Funktion des Zeitpunkts des Abonnements.

Ich habe jedoch das Gefühl, dass heiß vs. kalt immer noch eine Quelle der Verwirrung ist. Hier also meine Fragen:

  • Sind alle RX-Observables standardmäßig kalt (mit Ausnahme von Subjekten)?

    Ich habe oft gelesen, dass Ereignisse die typische Metapher für heiße Observables sind, aber ich habe auch das gelesen Rx.fromEvent(input, 'click') ist eine Erkältung beobachtbar(?).

  • Gibt es/was sind die Rx-Operatoren, die eine kalte Observable in eine heiße Observable verwandeln (abgesehen von publishund share)?

    Wie funktioniert es zum Beispiel mit dem Rx-Operator? withLatestFrom? Lassen cold$ ein Cold Observable sein, das irgendwo abonniert wurde. Wille sth$.withLatestFrom(cold$,...) ein heißer Observable sein?

    Oder wenn ich es tue sth1$.withLatestFrom(cold$,...), sth2$.withLatestFrom(cold$,...) und abonnieren sth1 und sth2sehe ich immer den gleichen Wert für beide sth?

  • ich dachte Rx.fromEvent erzeugt kalte Observablen, aber das ist nicht der Fall, wie in einer der Antworten erwähnt. Trotzdem wundert mich dieses Verhalten: https://codepen.io/anon/pen/NqQMJR?editors=101. Unterschiedliche Abonnements erhalten unterschiedliche Werte von demselben Observable. War das nicht click Veranstaltung geteilt?

  • Die Aussage „Alle Beobachter werden die gleiche Folge von Werten konsumieren“ zu den kalten Observablen ist nicht wahr. Das stimmt meistens, aber selbst der einfache Fall der Mutation eines Elements in einem Array, das ich in ein Observable umwandele, bedeutet, dass sich die Werte ändern. Und ich könnte ebenso einen beobachtbaren Zufallszahlengenerator erstellen, der kalt wäre, aber selten Zahlen wiederholt.

    – Rätselhaftigkeit

    22. Februar 2016 um 20:43 Uhr

  • Das ist richtig. Eigentlich ist genau das der Fall, der im verlinkten Codepen vorkommt und der damals meine Fragen generiert hat. Hoffentlich ist meine Antwort klarer darüber, was im Abonnement passiert.

    – Benutzer3743222

    22. Februar 2016 um 20:49 Uhr


Heise und kalte Observable Gibt es „heise und „kalte Operatoren
Benutzer3743222

Ich komme ein paar Monate später auf meine ursprüngliche Frage zurück und wollte in der Zwischenzeit die gewonnenen Erkenntnisse teilen. Ich werde den folgenden Code als Erklärungsunterstützung verwenden (jsfiddle):

var ta_count = document.getElementById('ta_count');
var ta_result = document.getElementById('ta_result');
var threshold = 3;

function emits ( who, who_ ) {return function ( x ) {
  who.innerHTML = [who.innerHTML, who_ + " emits " + JSON.stringify(x)].join("\n");
};}

var messages$ = Rx.Observable.create(function (observer){
  var count= 0;
  setInterval(function(){
    observer.onNext(++count);
  }, 1000)
})
.do(emits(ta_count, 'count'))
.map(function(count){return count < threshold})
.do(emits(ta_result, 'result'))

messages$.subscribe(function(){});

Wie in einer der Antworten erwähnt, führt die Definition eines Observable zu einer Reihe von Rückrufen und Parameterregistrierungen. Der Datenfluss muss angestoßen werden, und das geschieht über die subscribe Funktion. Ein (zur Veranschaulichung vereinfachter) detaillierter Ablauf findet sich danach.

Vereinfachtes Flussdiagramm

Observables sind standardmäßig kalt. Das Abonnieren eines Observables führt dazu, dass eine Upstream-Kette von Abonnements stattfindet. Die letzte Subskription führt zur Ausführung einer Funktion, die eine Quelle handhabt und ihre Daten an ihren Beobachter ausgibt.

Dieser Beobachter sendet seinerseits Daten an den nächsten Beobachter, was zu einem stromabwärtigen Datenfluss bis hinunter zum Senkenbeobachter führt. Die folgende vereinfachte Abbildung zeigt Abonnement- und Datenflüsse, wenn zwei Abonnenten dasselbe Observable abonnieren.

Kalt beobachtbares vereinfachtes Flussdiagramm

Hot Observables können entweder durch die Verwendung eines Subjekts oder durch die erstellt werden multicast Operator (und seine Derivate, siehe Anmerkung 3 unten).

Die multicast Der Operator unter der Haube verwendet ein Subjekt und gibt ein verbindbares Observable zurück. Alle Abonnements für den Operator sind Abonnements für das innere Subjekt. Wann connect aufgerufen wird, abonniert das innere Subjekt das Upstream-Observable und Daten fließen Downstream. Subjekte manipulieren intern eine Liste von abonnierten Beobachtern und senden eingehende Daten per Multicast an alle abonnierten Beobachter.

Das folgende Diagramm fasst die Situation zusammen.

Hot beobachtbares vereinfachtes Flussdiagramm

Am Ende kommt es eher darauf an, den Datenfluss zu verstehen, der durch das Beobachtermuster und die Implementierung der Operatoren verursacht wird.

Zum Beispiel, wenn obs ist heiß, ist hotOrCold = obs.op1 kalt oder heiß? Wie auch immer die Antwort lautet:

  • wenn es keine Abonnenten gibt obs.op1es fließen keine Daten durch op1. Wenn es heiße Abonnenten gäbe obsdas bedeutet obs.op1 möglicherweise Daten verloren haben
  • angenommen das op1 ist kein Multicast-ähnlicher Betreiber, der sich zweimal anmeldet hotOrCold wird zweimal abonnieren op1und jeder Wert von obs wird zweimal durchfließen op1.

Anmerkungen :

  1. Diese Informationen sollten für Rxjs v4 gültig sein. Obwohl die Version 5 erhebliche Änderungen erfahren hat, gilt das meiste immer noch wörtlich.
  2. Abbestellungs-, Fehler- und Vervollständigungsabläufe werden nicht dargestellt, da sie nicht Gegenstand der Frage sind. Scheduler werden ebenfalls nicht berücksichtigt. Sie beeinflussen unter anderem das Timing des Datenflusses, aber a priori nicht dessen Richtung und Inhalt.
  3. Je nach Art des für Multicasting verwendeten Themas gibt es verschiedene abgeleitete Multicasting-Operatoren:


Subject type | `Publish` Operator | `Share` operator
------------------ | --------------------------- | -----------------
Rx.Subject | Rx.Observable.publish | share
Rx.BehaviorSubject | Rx.Observable.publishValue | shareValue
Rx.AsyncSubject | Rx.Observable.publishLast | N/A
Rx.ReplaySubject | Rx.Observable.replay | shareReplay

Aktualisieren : Siehe auch die folgenden Artikel, hierund da) zu diesem Thema von Ben Lesh.

Weitere Details zu Themen finden Sie in dieser anderen SO-Frage: Was ist die Semantik verschiedener RxJS-Themen?

  • tolles Studium. Vielen Dank, dass Sie dies geteilt haben! Könnten Sie eine Erklärung hinzufügen, was „Publish-Operator“ und „Share-Operator“ bedeuten?

    – Iwan Kleschnin

    17. Januar 2016 um 10:06 Uhr

  • Die publish Betreiber sind die multicast Operator mit einer anderen Art von Subjekten, die als Parameter übergeben werden. Zum publish siehe zb hier: github.com/Reactive-Extensions/RxJS/blob/master/src/core/linq/…. share Operatoren erhält man durch Anhängen .refCount() zum publish Betreiber. Zum share siehe zum Beispiel github.com/Reactive-Extensions/RxJS/blob/master/src/core/linq/….

    – Benutzer3743222

    17. Januar 2016 um 13:31 Uhr

  • Es wäre immer noch gut, Themen richtig zu dokumentieren (aktuelle Dokumentation kann schwer herauszufinden sein). Ich denke, der beste Weg ist, wenn Sie eine bestimmte Frage zu diesem Thema protokollieren (kein Wortspiel beabsichtigt). Es würde den Rahmen sprengen, dies dort zu beantworten, und es würde erlauben, weitere Details hinzuzufügen. Die vorliegende Antwort ist bereits lang, und ich möchte sie auf die Frage konzentrieren. Frage könnte sein what are the semantics of the miscellaneous kinds of Rxjs subjects oder wie auch immer Sie es finden, um es kurz zu formulieren.

    – Benutzer3743222

    17. Januar 2016 um 13:40 Uhr


  • Du hast recht. Ich habe eine Frage gepostet: stackoverflow.com/questions/34849873/….

    – Iwan Kleschnin

    18. Januar 2016 um 8:09 Uhr

  • Und noch eine Frage zu “onComplete” hier stackoverflow.com/questions/34850043/…. Vielleicht hast du das auch schon für dich selbst ausgearbeitet. Operatortitel sind jetzt klar, danke.

    – Iwan Kleschnin

    18. Januar 2016 um 8:23 Uhr

Heise und kalte Observable Gibt es „heise und „kalte Operatoren
Whymarrh

Ihre Zusammenfassung und die verknüpfte Frage sind beide korrekt. Ich denke, die Terminologie kann Sie verwirren. Ich schlage vor, Sie stellen sich heiße und kalte Observable als aktive bzw. passive Observable vor.

Das heißt, ein aktives (heißes) Observable gibt Elemente aus, unabhängig davon, ob jemand abonniert hat oder nicht. Das kanonische Beispiel, wiederum, Schaltflächenklick-Ereignisse treten auf, unabhängig davon, ob jemand ihnen zuhört oder nicht. Diese Unterscheidung ist wichtig, denn wenn ich beispielsweise auf eine Schaltfläche klicke und dann Schaltflächenklicks (in dieser Reihenfolge) abonniere, sehe ich den bereits erfolgten Schaltflächenklick nicht.

Ein passives (kaltes) Observable wartet, bis ein Abonnent existiert, bevor es Items aussendet. Stellen Sie sich eine Schaltfläche vor, auf die Sie nicht klicken können, bis jemand die Ereignisse abhört – dies würde sicherstellen, dass Sie immer jedes einzelne Klickereignis sehen.

Sind alle Rx-Observables standardmäßig “kalt” (oder passiv)? Nein, Rx.fromEvent(input, 'click') zum Beispiel ist ein heißes (oder aktives) Observable.

Das habe ich auch gelesen Rx.fromEvent(input, 'click') ist eine Erkältung beobachtbar (?)

Das ist nicht der Fall.

Gibt es Rx-Operatoren, die eine kalte Observable in eine heiße Observable verwandeln?

Das Konzept, ein heißes (aktives) Observable in ein kaltes (passives) Observable umzuwandeln, ist folgendes: Sie müssen die Ereignisse aufzeichnen, die passieren, während nichts abonniert ist, und diese Elemente (auf verschiedene Weise) künftigen Abonnenten anbieten. Eine Möglichkeit, dies zu tun, ist die Verwendung von a Fach. Sie könnten zum Beispiel a verwenden ReplaySubject um ausgegebene Elemente zu puffern und sie für zukünftige Abonnenten wiederzugeben.

Die beiden von Ihnen genannten Operatoren (publish und share) verwenden beide Subjekte intern, um diese Funktionalität anzubieten.

Wie funktioniert es mit dem Rx-Operator? withLatestFrom? Lassen cold$ ein Cold Observable sein, das abonniert wurde. Wille something$.withLatestFrom(cold$,...) ein heißer Observable sein?

Wenn something ist ein heißes Observable, dann ja. Wenn something ist eine Kälte beobachtbar, dann nein. Gehen wir zurück zum Ereignisbeispiel, wenn something ist ein Stream von Schaltflächenklick-Ereignissen:

var clickWith3 = Rx.fromEvent(input, 'click')
    .withLatest(Rx.Observable.from([1, 2, 3]);

Oder wenn ich es tue foo$.withLatestFrom(cold$,...), bar$.withLatestFrom(cold$,...) und abonnieren foo und barsehe ich immer die gleichen Werte für beide?

Nicht immer. Nochmals, wenn foo und bar sind beispielsweise Klicks auf unterschiedliche Schaltflächen, dann würden Sie unterschiedliche Werte sehen. Auch wenn es sich um dieselbe Schaltfläche handelt, wenn Ihre Kombinationsfunktion (das 2 withLatest) nicht das gleiche Ergebnis für die gleichen Eingaben zurückgibt, würden Sie nicht die gleichen Werte sehen (weil es zweimal aufgerufen würde, wie unten erläutert).

ich dachte Rx.fromEvent erzeugt kalte Observablen, aber das ist nicht der Fall, wie in einer der Antworten erwähnt. Trotzdem wundert mich dieses Verhalten: codepen.io/anon/pen/NqQMJR?editors=101. Unterschiedliche Abonnements erhalten unterschiedliche Werte von demselben Observable. War das nicht click Veranstaltung geteilt?

Ich verweise Sie auf diese großartige Antwort von Enigmativity auf eine Frage, die ich zu demselben Verhalten hatte. Diese Antwort wird es viel besser erklären, als ich es kann, aber der Kern davon ist, dass die Quelle (das Klickereignis) “geteilt” ist, ja, aber Ihre Operationen darauf sind es nicht. Wenn Sie nicht nur das Click-Event, sondern auch die Operation teilen möchten, müssen Sie dies ausdrücklich tun.

  • Or if I do foo$.withLatestFrom(cold$,...), bar$.withLatestFrom(cold$,...) and subscribe to foo and bar, will I always see the same values for both? Meine Frage war eher ob der Wert abgenommen wird cold$ wird in beiden Fällen gleich sein. Mein Problem ist die Semantik von withLatestFrom. Ich verstehe, dass wir zwei verschiedene Abonnements für kalt $ haben, also würde ich erwarten, dass zwei verschiedene Werte extrahiert werden, abhängig vom Zeitpunkt des Abonnements, die die Semantik des Operators zerstören, also hatte ich erwartet, dass der Operator sich umdreht cold$ in einen heißen Strom. Aber am besten ist es zu testen und ich werde bald Antworten posten.

    – Benutzer3743222

    7. September 2015 um 0:01 Uhr


values in Ihrem Codepen ist faul – nichts passiert, bis sich etwas anmeldet, an welchem ​​​​Punkt es durchläuft und es verdrahtet. In Ihrem Beispiel werden also, obwohl Sie dieselbe Variable abonnieren, zwei verschiedene Streams erstellt. eine für jeden abonnierten Anruf.

Sie können sich vorstellen values als Generator von Streams für click damit map befestigt.

.share() am Ende dieser Karte würde das erwartete Verhalten erzeugen, da es sich implizit anmeldet.

Es ist keine Antwort auf alle Ihre Fragen (ich würde gerne alle wissen!), aber sicher alle fromEvent Observables sind heiß. Click scheint nicht zu sein, weil es kein “kontinuierliches” Ereignis wie Mousemove ist, aber trotzdem ein Abonnement der Quelle (addEventListener oder on Aufruf) wird nur einmal ausgeführt, wenn Observable erstellt wird. Es ist also heiß. Sie können es im Quellcode des Operators sehen Hier und dort – erstellt beobachtbar ist shared unabhängig von Name oder Quelle des Ereignisses.

897110cookie-checkHeiße und kalte Observable: Gibt es „heiße“ und „kalte“ Operatoren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy