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
etshare
)?par exemple, comment fonctionne-t-il avec l'opérateur RX
withLatestFrom
? Quecold$
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$,...)
etsth1
etsth2
, est-ce que je verrai toujours la même valeur pour les deuxsth
? -
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 leclick
événement partagé?
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.
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.
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.
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 dansop1
. Si il y avait les abonnés à hotobs
, qui signifieobs.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 deobs
coulera deux fois àop1
.
Notes:
- 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.
- 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.
- 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?
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
? Quecold$
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
etbar
, 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énementclick
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.
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.
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 là - créé observable est share
d Peu importe le nom ou la source de l'événement.