Observables chaud et froid: y a-t-il des opérateurs "chaud" et "froid"?

j'ai examiné la question suivante SO: Qu'est-ce que les observables chaud et froid?

pour résumer:

  • un observable à froid émet ses valeurs lorsqu'il a un observateur pour les consommer, c.-à-d. que la séquence des valeurs reçues par les observateurs est indépendante du temps d'abonnement. Tous les observateurs consommeront la même séquence de valeurs.
  • une valeur d'émission observable à chaud indépendamment de ses abonnements, c'est-à-dire que les valeurs reçues par les observateurs sont fonction de l'Heure de l'abonnement.

pourtant, je me sens comme le chaud contre le froid est toujours une source de confusion. Voici donc mes questions:

  • tous les RX observables sont-ils froids par défaut (à l'exception des sujets)?

    je lis souvent que les événements sont la métaphore typique des observables chauds, mais je lis aussi Rx.fromEvent(input, 'click') est un froid observables(?).

  • y a-t-il/qu'est-ce que les opérateurs Rx qui transforment un observable à froid en observable à chaud (à l'exception de publish et share )?

    par exemple, comment fonctionne-t-il avec l'opérateur RX withLatestFrom ? Que cold$ soit un observable du froid auquel on a souscrit quelque part. sth$.withLatestFrom(cold$,...) sera-t-il observable à chaud?

    ou si je le fais sth1$.withLatestFrom(cold$,...), sth2$.withLatestFrom(cold$,...) et sth1 et sth2 , est-ce que je verrai toujours la même valeur pour les deux sth ?

  • je pensais Rx.fromEvent crée des observables froids mais ce n'est pas le cas, comme mentionné dans l'une des réponses. Cependant, je suis encore perplexe par ce comportement : codepen.io/anon/pen / NqQMJR?editors=101 . Des souscriptions différentes obtiennent des valeurs différentes du même observable. N'était pas le click événement partagé?

51
demandé sur Jason Aller 2015-08-24 22:42:45

4 réponses

je reviens quelques mois plus tard à ma question d'origine et je voulais partager les connaissances acquises dans l'intervalle. J'utiliserai le code suivant comme support d'explication ( 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(){});

comme mentionné dans l'une des réponses, la définition d'une variable observable mène à une série de callback et d'enregistrement de paramètres. Le flux de données doit être activé, et cela se fait via la fonction subscribe . Un (simplifié pour illustration) un flux détaillé peut être trouvé par la suite.

Simplified flow diagram

Observables sont froids par défaut. L'abonnement à un observable se traduira par une chaîne d'abonnements en amont. Le dernier abonnement mène à l'exécution d'une fonction qui manipule une source et émet ses données à son observateur.

que l'observateur émet à son tour à l'observateur suivant, il en résulte un flux de données en aval, jusqu'à l'observateur du puits. L'illustration simplifiée suivante montre les flux d'abonnement et de données lorsque deux abonnés souscrivent au même observable.

Cold observable simplified flow diagram

Les observables à chaud

peuvent être créés soit en utilisant un sujet, soit par l'intermédiaire de l'opérateur multicast (et ses dérivés, Voir Note 3 ci-dessous).

le multicast opérateur sous le capot fait usage d'un sujet et renvoie un observable connectable. Tous les souscriptions à l'opérateur seront des souscriptions au sujet intérieur. Quand connect est appelé, le sujet interne souscrit à l'observable en amont, et les flux de données en aval. Les sujets manipulent à l'interne une liste d'observateurs abonnés et multidiffusent les données entrantes à tous les observateurs abonnés.

le diagramme suivant résume la situation.

Hot observable simplified flow diagram

en fin de compte, il est plus important de comprendre le flux de données causé par le modèle d'observateur et la mise en œuvre des opérateurs.

par exemple, si obs est chaud, hotOrCold = obs.op1 est froid ou chaud? Quelle que soit la réponse:

  • s'il n'y a pas d'abonnés à obs.op1 , aucune donnée ne circulera dans op1 . Si il y avait les abonnés à hot obs , qui signifie obs.op1 auront peut-être perdu des données
  • suppose que op1 n'est pas un opérateur multicast-like, souscrivant deux fois à hotOrCold souscrira deux fois à op1 , et chaque valeur de obs coulera deux fois à op1 .

Notes:

  1. cette information devrait être valide pour Rxjs v4. Alors que la version 5 a disparu grâce à des changements considérables, la plupart d'entre eux continuent de s'appliquer mot à mot.
  2. les flux de désabonnement, d'erreur et d'achèvement ne sont pas représentés elles n'entrent pas dans le cadre de la question. Les planificateurs sont également pas prise en compte. Entre autres choses, ils influencent le moment de le flux de données, mais a priori pas sa direction et son contenu.
  3. selon le type de sujet utilisé pour la multidiffusion, il y a différents dérivés de multidiffusion opérateurs:

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

Update : Voir aussi les articles suivants, ici , et là ) sur ce sujet par Ben Lesh.

D'autres détails sur les sujets peuvent être trouvés dans cette autre SO question : Quelle est la sémantique des différents sujets rxjs?

65
répondu user3743222 2018-02-26 16:26:14

votre résumé, et la question liée sont tous les deux corrects, je pense que la terminologie peut vous induire en erreur. Je vous propose de considérer les observables chauds et froids comme des observables actifs et passifs (respectivement).

, c'est-à-dire qu'un observable actif (à chaud) émettra des articles, que quelqu'un ait souscrit ou non. L'exemple canonique, encore une fois, les événements de clic de bouton se produisent si quelqu'un les écoute ou non. Cette distinction est importante parce que, si, pour exemple, je clique sur un bouton et puis je m'abonne à des clics de bouton (dans cet ordre), Je ne verrai pas le clic de bouton qui s'est déjà produit.

passif " (froid) observables attendre un abonné existe avant d'émettre des articles. Imaginez un bouton où vous ne pouvez pas cliquer dessus jusqu'à ce que quelqu'un écoute les événements-cela vous assurerait de toujours voir chaque événement de clic.

est-ce que tous les observables Rx sont "froids" (ou passifs) par défaut? Aucun, Rx.fromEvent(input, 'click') par exemple est un chaud (ou actif) observable.

j'ai aussi lu que Rx.fromEvent(input, 'click') est un froid observables(?)

ce n'est pas le cas.

y a-t-il des opérateurs Rx qui transforment un observable à froid en observable à chaud?

le concept de transformation d'un observable chaud (actif) en un observable froid (passif) est le suivant: consignez les événements qui se produisent alors que rien n'est souscrit et offrez ces articles (de diverses façons) aux abonnés qui se présentent à l'avenir. Une façon de le faire est d'utiliser un sujet . Par exemple, vous pouvez utiliser un ReplaySubject pour amortir les articles émis et les rejouer aux abonnés futurs.

les deux opérateurs que vous avez nommés ( publish et share ) utilisent tous deux des objets internes pour offrir cette fonctionnalité.

Comment fonctionne-t-il avec l'opérateur RX withLatestFrom ? Que cold$ soit un observable à froid auquel on a souscrit. something$.withLatestFrom(cold$,...) sera-t-il observable à chaud?

Si something est une chaude observable, alors oui. Si something est un froid observable, alors non. Pour revenir à l'exemple des événements, si something est un flux de bouton cliquez sur événements:

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

ou si je fais foo$.withLatestFrom(cold$,...), bar$.withLatestFrom(cold$,...) et abonnez-vous à foo et bar , est-ce que je verrai toujours les mêmes valeurs pour les deux?

pas toujours. Encore une fois, si foo et bar sont des clics sur des boutons différents par exemple, alors vous verriez des valeurs différentes. Ainsi, même si elles ont le même bouton, si votre fonction de combinaison (le 2ème argument withLatest ) ne renvoie pas le même résultat pour les mêmes entrées, alors vous ne voyez pas les mêmes valeurs (parce qu'il serait appelé deux fois, comme expliqué ci-dessous).

j'ai pensé Rx.fromEvent crée froid observables mais qui n'est pas le cas, comme mentionné dans l'une des réponses. Cependant, je suis encore perplexe par ce comportement: codepen.io/anon/pen / NqQMJR?editors=101 . Des souscriptions différentes obtiennent des valeurs différentes du même observable. L'événement click n'a-t-il pas été partagé?

je vous pointerai à cette grande réponse par Enigmativity à une question que j'ai eu sur le même comportement. Que répondre à l'expliquera beaucoup mieux que moi, mais l'essentiel, c'est que la source (l'événement click) est "partagé", oui, mais vos opérations sur il ne le sont pas. Si vous voulez partager non seulement l'événement de clic, mais aussi l'opération, vous aurez besoin de le faire explicitement.

7
répondu Whymarrh 2017-05-23 11:54:53

values dans votre codepen est paresseux - rien n'arrive jusqu'à ce que quelque chose s'abonne, à quel point il court à travers et les fils vers le haut. Donc dans votre exemple, bien que vous soyez abonné à la même variable, il crée deux flux différents; un pour chaque appel d'abonnement.

vous pouvez penser à values comme étant un générateur de flux pour click avec ce map attaché.

.share() sur la fin de ce plan d' créer le comportement que nous attendons, car il est implicitement abonnement.

4
répondu electrichead 2015-09-03 02:08:22

ce n'est pas une réponse à toutes vos questions (je voudrais les connaître toutes!) mais bien sûr, tous les fromEvent Observables sont chauds. Le clic ne semble pas être parce que ce n'est pas un événement "continu" comme mousemove, mais de toute façon l'abonnement à la source (appel addEventListener ou on ) ne se fait qu'une seule fois, quand Observable est créé. Donc, c'est chaud. Vous pouvez le voir dans le code source de l'opérateur ici et - créé observable est share d Peu importe le nom ou la source de l'événement.

3
répondu Eryk Napierała 2015-08-25 10:25:07