javascript - react - rxjs operators
¿Por qué necesitamos usar flatMap? (9)
Aquí para mostrar la implementación equivalente de un flatMap usando suscriptores.
Sin flatMap:
this.searchField.valueChanges.debounceTime(400)
.subscribe(
term => this.searchService.search(term)
.subscribe( results => {
console.log(results);
this.result = results;
}
);
);
Con flatMap:
this.searchField.valueChanges.debounceTime(400)
.flatMap(term => this.searchService.search(term))
.subscribe(results => {
console.log(results);
this.result = results;
});
http://plnkr.co/edit/BHGmEcdS5eQGX703eRRE?p=preview
Espero que pueda ayudar.
Olivier
Estoy empezando a usar RxJS y no entiendo por qué en este ejemplo necesitamos usar una función como
flatMap
o
concatAll
;
¿Dónde está la matriz de matrices aquí?
var requestStream = Rx.Observable.just(''https://api.github.com/users'');
var responseMetastream = requestStream
.flatMap(function(requestUrl) {
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
});
responseMetastream.subscribe(url => {console.log(url)})
Si alguien puede explicar visualmente lo que está sucediendo, será muy útil.
Con flatMap
var requestStream = Rx.Observable.just(''https://api.github.com/users'');
var responseMetastream = requestStream
.flatMap(function(requestUrl) {
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
});
responseMetastream.subscribe(json => {console.log(json)})
Sin planoMapa
var requestStream = Rx.Observable.just(''https://api.github.com/users'');
var responseMetastream = requestStream
.map(function(requestUrl) {
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
});
responseMetastream.subscribe(jsonStream => {
jsonStream.subscribe(json => {console.log(json)})
})
Cuando comencé a echar un vistazo a
Rxjs
también me topé con esa piedra.
Lo que me ayudó es lo siguiente:
-
documentación de reactivex.io.
Por ejemplo, para
flatMap
: http://reactivex.io/documentation/operators/flatmap.html -
documentación de rxmarbles:
http://rxmarbles.com/
.
No encontrará
flatMap
allí, debe buscarmergeMap
enmergeMap
lugar (otro nombre). - la introducción a Rx que te has estado perdiendo: https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 . Aborda un ejemplo muy similar. En particular, aborda el hecho de que una promesa es similar a un observable que emite un solo valor.
-
finalmente mirando la información de tipo de RxJava. Javascript no se escribe no ayuda aquí. Básicamente, si
Observable<T>
denota un objeto observable que empuja valores de tipo T,flatMap
toma una función de tipoT'' -> Observable<T>
como argumento y devuelveObservable<T>
.map
toma una función de tipoT'' -> T
y devuelveObservable<T>
.Volviendo a su ejemplo, tiene una función que produce promesas a partir de una cadena de URL. Entonces
T'' : string
yT : promise
. Y por lo que dijimos antes de lapromise : Observable<T''''>
, entoncesT : Observable<T''''>
, conT'''' : html
. Si pones esa función promotora en elmap
, obtienesObservable<Observable<T''''>>
cuando lo que quieres esObservable<T''''>
: quieres que el observable emita los valoreshtml
.flatMap
se llama así porque aplana (elimina una capa observable) el resultado delmap
. Dependiendo de sus antecedentes, esto podría ser chino para usted, pero todo me quedó claro con la información de mecanografía y el dibujo desde aquí: http://reactivex.io/documentation/operators/flatmap.html .
No es una matriz de matrices. Es un observable de observable (s).
Lo siguiente devuelve un flujo de cadena observable.
requestStream
.map(function(requestUrl) {
return requestUrl;
});
Si bien esto devuelve una secuencia observable de secuencia observable de JSON
requestStream
.map(function(requestUrl) {
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
});
flatMap
aplana el observable automáticamente para que podamos observar el flujo json directamente
Sencillo:
[1,2,3].map(x => [x, x * 10])
// [[1, 10], [2, 20], [3, 30]]
[1,2,3].flatMap(x => [x, x * 10])
// [1, 10, 2, 20, 3, 30]]
Un Observable es un objeto que emite una secuencia de eventos: Siguiente, Error y Completado.
Cuando su función devuelve un Observable, no devuelve una secuencia, sino una instancia de Observable.
El operador
flatMap
simplemente asigna esa instancia a una secuencia.
Ese es el comportamiento de
flatMap
en comparación con
map
: ejecuta la función dada y aplana el objeto resultante en una secuencia.
flatMap
transforma los elementos emitidos por un observable en nuevos observables, luego aplana las emisiones de esos en un solo observable.
Consulte el siguiente escenario donde
get("posts")
devuelve un Observable que es "aplanado" por
flatMap
.
myObservable.map(e => get("posts")).subscribe(o => console.log(o));
// this would log Observable objects to console.
myObservable.flatMap(e => get("posts")).subscribe(o => console.log(o));
// this would log posts to console.
Las personas tienden a complicar más las cosas al dar la definición que dice:
flatMap transforma los elementos emitidos por un observable en observables, luego aplana las emisiones de esos en un solo observable
Juro que esta definición todavía me confunde, pero voy a explicarla de la manera más simple, utilizando un ejemplo.
Nuestra situación : tenemos un observable que devuelve datos (URL simple) que vamos a utilizar para hacer una llamada HTTP que devolverá un observable que contenga los datos que necesitamos para que pueda visualizar la situación de esta manera:
Observable 1
|_
Make Http Call Using Observable 1 Data (returns Observable_2)
|_
The Data We Need
como puede ver, no podemos llegar a los datos que necesitamos directamente, así que la primera forma de recuperar los datos es que podemos usar suscripciones normales como esta:
Observable_1.subscribe((URL) => {
Http.get(URL).subscribe((Data_We_Need) => {
console.log(Data_We_Need);
});
});
esto funciona, pero como puede ver, tenemos que anidar suscripciones para obtener nuestros datos, actualmente no se ve mal, pero imagine que tenemos 10 suscripciones anidadas que serían imposibles de mantener.
así que una mejor manera de manejar esto es simplemente usar el operador
flatMap
que hará lo mismo pero nos hace evitar esa suscripción anidada:
Observable_1
.flatMap(URL => Http.get(URL))
.subscribe(Data_We_Need => console.log(Data_We_Need));
[''a'',''b'',''c''].flatMap(function(e) {
return [e, e+ ''x'', e+ ''y'', e+ ''z'' ];
});
//[''a'', ''ax'', ''ay'', ''az'', ''b'', ''bx'', ''by'', ''bz'', ''c'', ''cx'', ''cy'', ''cz'']
[''a'',''b'',''c''].map(function(e) {
return [e, e+ ''x'', e+ ''y'', e+ ''z'' ];
});
//[Array[4], Array[4], Array[4]]
Utiliza flatMap cuando tiene un Observable cuyos resultados son más Observables.
Si tiene un observable producido por otro observable, no puede filtrarlo, reducirlo o asignarlo directamente porque tiene un Observable, no los datos. Si produce un observable, elija flatMap sobre el mapa; entonces estás bien
Como en el segundo fragmento, si está realizando una operación asincrónica, debe usar flatMap.
var source = Rx.Observable.interval(100).take(10).map(function(num){
return num+1
});
source.subscribe(function(e){
console.log(e)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>
var source = Rx.Observable.interval(100).take(10).flatMap(function(num){
return Rx.Observable.timer(100).map(() => num)
});
source.subscribe(function(e){
console.log(e)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>