videos son primaria para niños naturales natural luz luminosa las fuentes fuente ejemplos cuáles calor artificial javascript angular rxjs reactive-programming rxjs5

javascript - son - Observables en caliente y en frío: ¿hay operadores ''en caliente'' y ''en frío''?



fuentes de luz natural y artificial para niños (4)

Revisé la siguiente pregunta SO: ¿Cuáles son los observables de frío y calor?

Para resumir:

  • un observable frío emite sus valores cuando tiene un observador para consumirlos, es decir, la secuencia de valores recibidos por los observadores es independiente del tiempo de suscripción. Todos los observadores consumirán la misma secuencia de valores.
  • un observable en caliente emite un valor independientemente de sus suscripciones, es decir, los valores recibidos por los observadores son una función del momento de la suscripción.

Sin embargo, siento que el calor y el frío siguen siendo una fuente de confusión. Asi que aqui están mis preguntas:

  • ¿Todos los observables de rx están fríos por defecto (con la excepción de los sujetos)?

    A menudo leo que los eventos son la metáfora típica de los observables en caliente, pero también leo que Rx.fromEvent(input, ''click'') es un observable en frío (?).

  • ¿Hay / qué son los operadores de Rx que convierten un observable frío en un observable caliente (aparte de publish y share )?

    Por ejemplo, ¿cómo funciona con el operador Rx withLatestFrom ? Deje que cold$ sea ​​un observable en frío al que se haya suscrito en algún lugar. ¿ sth$.withLatestFrom(cold$,...) será un observable caliente?

    O si hago sth1$.withLatestFrom(cold$,...), sth2$.withLatestFrom(cold$,...) y me suscribo a sth1 y sth2 , ¿siempre veré el mismo valor para ambas cosas?

  • Pensé que Rx.fromEvent crea observables fríos, pero ese no es el caso, como se menciona en una de las respuestas. Sin embargo, todavía estoy desconcertado por este comportamiento: codepen.io/anon/pen/NqQMJR?editors=101 . Suscripciones diferentes obtienen valores diferentes del mismo observable. ¿No se compartió el evento de click ?


No es una respuesta para todas sus preguntas (¡me gustaría fromEvent todas!), Pero sin duda, todas fromEvent Observables del fromEvent están de moda. El clic parece no ser porque no es un evento "continuo" como mousemove, sino que la suscripción a la fuente ( addEventListener o on call) se realiza solo una vez, cuando se crea Observable. Entonces hace calor. Puede verlo en el código fuente del operador here y there : el observable creado es share d sin importar cuál sea el nombre o la fuente del evento.


Regresaré unos meses más tarde a mi pregunta original y, mientras tanto, quería compartir el conocimiento adquirido. jsfiddle el siguiente código como soporte explicativo ( 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(){});

Como se menciona en una de las respuestas, la definición de un observable conduce a una serie de devolución de llamada y registro de parámetros. El flujo de datos debe iniciarse, y eso se hace a través de la función de subscribe . A continuación se puede encontrar un flujo detallado (simplificado para ilustración).

Los observables están fríos por defecto. Suscribirse a un observable dará como resultado una cadena ascendente de suscripciones. La última suscripción lleva a la ejecución de una función que manejará una fuente y emitirá sus datos a su observador.

Ese observador a su vez emite al siguiente observador, lo que resulta en un flujo de datos aguas abajo, hacia el observador de sumidero. La siguiente ilustración simplificada muestra los flujos de suscripción y datos cuando dos suscriptores se suscriben al mismo observable.

Los observables en caliente se pueden crear mediante el uso de un sujeto o mediante el operador de multicast (y sus derivados, consulte la Nota 3 a continuación).

El operador de multicast debajo del capó hace uso de un sujeto y devuelve un observable conectable. Todas las suscripciones al operador serán suscripciones al sujeto interno. Cuando se llama a connect , el sujeto interno se suscribe al observable en sentido ascendente y los datos fluyen en sentido descendente. Los sujetos manipulan internamente una lista de observadores suscritos y datos entrantes de multidifusión a todos los observadores suscritos.

El siguiente diagrama resume la situación.

Al final, es más importante comprender el flujo de datos causado por el patrón de observación y la implementación de los operadores.

Por ejemplo, si obs está caliente, ¿ hotOrCold = obs.op1 frío o caliente? Cualquiera que sea la respuesta es:

  • Si no hay suscriptores a obs.op1 , no obs.op1 datos a través de op1 . Si hubo suscriptores a hot obs , eso significa que obs.op1 posiblemente habrá perdido datos
  • suponiendo que op1 no es un operador de multidifusión, suscribirse dos veces a hotOrCold se suscribirá dos veces a op1 , y cada valor de obs fluirá dos veces a través de op1 .

Notas:

  1. Esta información debe ser válida para Rxjs v4. Si bien la versión 5 ha experimentado cambios considerables, la mayor parte todavía se aplica textualmente.
  2. Los flujos de cancelación de suscripción, error y finalización no están representados, ya que no están dentro del alcance de la pregunta. Los programadores tampoco se tienen en cuenta. Entre otras cosas, influyen en el momento del flujo de datos, pero a priori no en su dirección y contenido.
  3. Según el tipo de tema utilizado para la multidifusión, existen diferentes operadores de multidifusión derivados:

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

Actualización : Vea también los siguientes artículos, aquí y allá ) sobre ese tema de Ben Lesh.

Se pueden encontrar más detalles sobre los temas en esta otra pregunta SO: ¿Cuáles son las semánticas de los diferentes temas RxJS?


Su resumen y la pregunta vinculada son correctas, creo que la terminología puede confundirlo. Le propongo que piense en los observables fríos y calientes como observables activos y pasivos (respectivamente).

Es decir, un observable activo (activo) emitirá elementos independientemente de si alguien se ha suscrito o no. El ejemplo canónico, una vez más, los eventos de clic de botón ocurren si alguien los está escuchando o no. Esta distinción es importante porque, por ejemplo, si hago clic en un botón y luego me suscribo a los clics de botón (en ese orden), no veré el clic de botón que ya ha sucedido.

Un observable pasivo (frío) esperará hasta que exista un suscriptor antes de emitir elementos. Imagine un botón donde no puede hacer clic en él hasta que alguien esté escuchando los eventos; esto garantizaría que siempre vea todos y cada uno de los eventos de clic.

¿Todos los observables de Rx son "fríos" (o pasivos) por defecto? No, Rx.fromEvent(input, ''click'') por ejemplo, es un observable activo (o activo).

También leí que Rx.fromEvent(input, ''click'') es un observable en frío (?)

Ese no es el caso.

¿Hay operadores Rx que convierten un observable frío en un observable caliente?

El concepto de convertir un observable caliente (activo) en un observable frío (pasivo) es el siguiente: debe registrar los eventos que suceden mientras nada está suscrito y ofrecer esos elementos (de varias maneras) a los suscriptores que se presenten en el futuro. Una forma de hacer esto es usar un Subject . Por ejemplo, podría usar un ReplaySubject para almacenar los elementos emitidos y reproducirlos en futuros suscriptores.

Los dos operadores que nombró ( publish y share ) usan temas internamente para ofrecer esa funcionalidad.

¿Cómo funciona con el operador Rx withLatestFrom ? Deje que cold$ sea ​​un observable en frío al que se haya suscrito. ¿ something$.withLatestFrom(cold$,...) será observable?

Si something es observable, entonces sí. Si something es un frío observable, entonces no. Volviendo al ejemplo de eventos, si something es una secuencia de eventos de clic de botón:

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

O si hago foo$.withLatestFrom(cold$,...), bar$.withLatestFrom(cold$,...) y me suscribo a foo y bar , ¿siempre veré los mismos valores para ambos?

No siempre. Nuevamente, si foo y bar son clics en diferentes botones, por ejemplo, entonces vería diferentes valores. Además, incluso si fueran el mismo botón, si su función de combinación (el segundo argumento de withLatest ) no devuelve el mismo resultado para las mismas entradas, entonces no vería los mismos valores (porque se llamaría dos veces, como explicado a continuación).

Pensé que Rx.fromEvent crea observables fríos, pero ese no es el caso, como se menciona en una de las respuestas. Sin embargo, todavía estoy desconcertado por este comportamiento: codepen.io/anon/pen/NqQMJR?editors=101 . Suscripciones diferentes obtienen valores diferentes del mismo observable. ¿No se compartió el evento de click ?

Te diré a esta gran respuesta de Enigmativity a una pregunta que tenía sobre el mismo comportamiento. Esa respuesta lo explicará mucho mejor de lo que puedo, pero lo esencial es que la fuente (el evento de clic) está "compartida", sí, pero sus operaciones no lo son. Si desea compartir no solo el evento de clic, sino también la operación en él, deberá hacerlo explícitamente.


values en su codepen son vagos: no sucede nada hasta que algo se suscribe, momento en el que se ejecuta y lo conecta. Entonces, en su ejemplo, aunque se está suscribiendo a la misma variable, está creando dos flujos diferentes; uno para cada llamada de suscripción.

Puede pensar en los values como un generador de secuencias para click con ese map adjunto.

.share() al final de ese mapa crearía el comportamiento que esperamos, porque se está suscribiendo implícitamente.