reactive-programming - rxjava - flatmap()
¿Cuál es la diferencia entre flatmap y switchmap en RxJava? (6)
Aquí está el otro: 101 líneas de largo example . Eso explica el problema para mí.
Como se dijo: obtiene el último observable (el más lento si se quiere) e ignora el resto.
Como resultado:
Time | scheduler | state
----------------------------
0 | main | Starting
84 | main | Created
103 | main | Subscribed
118 | Sched-C-0 | Going to emmit: A
119 | Sched-C-1 | Going to emmit: B
119 | Sched-C-0 | Sleep for 1 seconds for A
119 | Sched-C-1 | Sleep for 2 seconds for B
1123 | Sched-C-0 | Emitted (A) in 1000 milliseconds
2122 | Sched-C-1 | Emitted (B) in 2000 milliseconds
2128 | Sched-C-1 | Got B processed
2128 | Sched-C-1 | Completed
Ves que A fue ignorada.
La definición de rxjava doc de switchmap es bastante vaga y se vincula a la misma página que flatmap. ¿Cuál es la diferencia entre los dos operadores?
De acuerdo con la documentación ( http://reactivex.io/documentation/operators/flatmap.html )
el SwitchMap es como el flatMap PERO solo emitirá elementos del nuevo observable hasta que se haya emitido un nuevo evento desde la fuente observable.
El diagrama de mármol lo muestra bien. Observe la diferencia en los diagramas:
En switchMap
la segunda emisión original ( mármol verde ) no emite su segunda emisión mapeada ( casilla verde ), ya que la tercera emisión original ( mármol azul ) ha comenzado y ya emitió su primera emisión mapeada ( diamante azul ). En otras palabras, solo ocurre la primera de las dos emisiones verdes asignadas ; no se emite ningún cuadrado verde porque el diamante azul lo golpeó.
En flatMap
, se flatMap
todos los resultados asignados, incluso si están "obsoletos". En otras palabras, tanto la primera como la segunda de las emisiones verdes mapeadas suceden: se habría emitido un cuadrado verde (si usaban una función de mapa consistente, ya que no lo hicieron, se ve el segundo diamante verde, aunque se emite después el primer diamante azul)
mapa plano
Me encontré con esto al implementar "búsqueda instantánea", es decir, cuando el usuario escribe en un cuadro de texto, y los resultados aparecen casi en tiempo real con cada golpe de tecla. La solución parece ser:
- Tener un tema, como PublishSubject of String
- En el cuadro de texto, cambie la devolución de llamada, invoque .onNext (texto)
- aplicar .debounce filter para limitar las consultas del servidor
- aplicar .switchMap para realizar una consulta del servidor - tomando el término de búsqueda y devolviendo Observable of SearchResponse
- aplicar .subscribe con un método que consume SearchResponse y actualiza la UI.
Con flatMap, los resultados de la búsqueda pueden ser obsoletos, ya que las respuestas de búsqueda pueden volver a estar desordenadas. Para solucionar esto, se debe usar switchMap, ya que garantiza que se anule la suscripción de un antiguo observable una vez que se proporcione uno más nuevo.
Por lo tanto, en resumen, flatMap se debe usar cuando todos los resultados importan, independientemente de su tiempo, y se debe usar switchMap cuando solo sean relevantes los resultados del último Observable.
Ninguna discusión de flatMap está completa sin comparar y contrastar con switchMap
, concatMap
y concatMapEager
.
Todos estos métodos toman un Func1
que transforma el flujo en Observable
que luego se emiten; la diferencia es cuando los Observable
devueltos se suscriben y dan de baja, y si y cuando esas emisiones de esos Observable
son emitidas por el operador ____Map
en cuestión.
-
flatMap
suscribe a tantosObservable
emitidos como sea posible. (Es un número dependiente de la plataforma, es decir, un número menor en Android) Úselo cuando la orden NO sea importante y desee emisiones lo antes posible. concatMap
suscribe al primerObservable
y solo se suscribe al siguienteObservable
cuando el anterior se haya completado. Úselo cuando el orden sea importante y desee conservar recursos. Un ejemplo perfecto es aplazar una llamada de red comprobando primero la memoria caché. Suele ser seguido por.first()
o.takeFirst()
para evitar hacer un trabajo innecesario.http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/
concatMapEager
funciona de manera similar, pero se suscribe a la mayor cantidad posible (depende de la plataforma) pero solo se emitirá una vez que se haya completado elObservable
anterior. Perfecto cuando tiene que realizar un gran procesamiento en paralelo, pero (a diferencia de flatMap) desea mantener el orden original.-
switchMap
se suscribirá al últimoObservable
que encuentre y se dará de baja de todos losObservable
anteriores. Esto es perfecto para casos como sugerencias de búsqueda: una vez que un usuario ha cambiado su consulta de búsqueda, la solicitud anterior ya no tiene ningún interés, por lo que se cancela la suscripción, y un punto final Api con buen comportamiento cancelará la solicitud de red.
Si devuelve Observable
que no se subscribeOn
otro hilo, todos los métodos anteriores pueden comportarse de manera similar. El comportamiento interesante y útil surge cuando permite que los Observable
anidados actúen sobre sus propios hilos. Entonces puede obtener muchos beneficios del procesamiento en paralelo, y darse de baja de manera inteligente o no subscribirse de Observable
s que no interesan a su Subscriber
.
-
amb
también puede ser de interés. Dado cualquier número deObservable
, emite los mismos elementos que el primerObservable
que emite algo emite. Eso podría ser útil cuando tienes varias fuentes que podrían / deberían devolver lo mismo y quieres rendimiento. Por ejemplo, ordenar, puede ordenar de forma rápida con un tipo de fusión y usar el que sea más rápido.
Si estás buscando un código de ejemplo
/**
* We switch from original item to a new observable just using switchMap.
* It´s a way to replace the Observable instead just the item as map does
* Emitted:Person{name=''Pablo'', age=0, sex=''no_sex''}
*/
@Test
public void testSwitchMap() {
Observable.just(new Person("Pablo", 34, "male"))
.switchMap(person -> Observable.just(new Person("Pablo", 0, "no_sex")))
.subscribe(System.out::println);
}
Puedes ver más ejemplos aquí https://github.com/politrons/reactive
switchMap una vez se llamó flatMapLatest en RxJS 4.
Básicamente solo pasa los eventos del último Observable y anula la suscripción del anterior.