share & LiveValue.from
Una ejecución de la cadena, muchos oyentes — y la versión que recuerda su último valor para quien llegue tarde.
Lección
Todos los operadores de esta sección construyen su propio
StreamController, así que la cadena que devuelven es de
suscripción única: escúchala dos veces y el segundo
oyente recibe un StateError. Ese comportamiento por defecto
es deliberado: mantiene la cadena fría, de modo que nada se ejecuta hasta
que alguien la consume, y mantiene honesto el estado por oyente. Pero
implica que dos widgets no pueden observar el mismo feed con debounce,
throttle y switchMap sin construirlo dos veces.
share() lo arregla. Conecta con el primer
oyente y difunde a todos los oyentes a partir de ahí, así que el trabajo
aguas arriba ocurre una vez por muchos que estén mirando. Un temporizador
de debounce, un socket, un map caro: uno de cada, no uno por suscriptor.
share({reset: true}) — el valor por defecto — ahora coincide
con el reset por recuento de Rx. Cuando el último oyente se va
antes de que la fuente haya completado, la suscripción
de aguas arriba se cancela y el siguiente oyente empieza una suscripción
nueva. Después de que la fuente completa, a un oyente
tardío se le sigue entregando un stream cerrado.
share(reset: false) es el comportamiento de 0.8.7: la
última cancelación cierra para siempre. Una resuscripción necesita una
fuente que permita un segundo listen —
Stream.fromIterable, Stream.multi,
FxEvents.defer, un broadcast — un
StreamController de suscripción única ya gastado sigue
sin poder volver a escucharse. Engancha todos los oyentes antes del
primer evento si la fuente es de un solo disparo, o mantén uno vivo.
share() tampoco recuerda: un oyente que llega
después de que haya pasado un evento simplemente se lo ha perdido. Para
una ventana de historial,
shareReplay es la página
siguiente. Cuando los rezagados necesitan el estado actual —que es
casi toda la UI—,
LiveValue es la respuesta, y
LiveValue.from(source) / LiveValue.seededFrom(seed,
source) construyen uno directamente desde un stream. Esos son
calientes: la suscripción se abre de inmediato, así que
los valores que llegan antes de que nadie escuche siguen actualizando
value, y close() cancela la fuente. Son
constructores con nombre en vez de una semilla opcional para que un
T nullable pueda sembrarse igualmente con null. Capa de
eventos de fxdart, siguiendo a share y
shareValue de Rx.
Demo 1 · Por qué un solo oyente es el comportamiento por defecto
Demo 2 · Una ejecución, dos oyentes
Pruébalo tú
Ejercicio: un LiveValue alimentado directamente desde un stream.
shareReplay — multicast que recuerda un búfer de historial ·
LiveValue — el compartir que recuerda: los suscriptores tardíos reciben primero el valor actual ·
tee — la respuesta del lado pull a dos lectores sobre una pasada, sin búfer ·
fork — dos cursores pull independientes sobre una fuente, a costa de un búfer