¿Por qué necesitamos usar flatMap?
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.
9 answers
Cuando empecé a echar un vistazo a Rxjs
también tropecé 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ás
flatMap
allí, debes mirarmergeMap
en su 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 ser escrito no ayuda aquí. Básicamente si
Observable<T>
denota un objeto observable que empuja valores de tipo T, entoncesflatMap
toma una función de tipoT' -> Observable<T>
como su argumento, y devuelveObservable<T>
.map
toma una función de tipoT' -> T
y devuelveObservable<T>
.Volviendo a tu ejemplo, tienes una función que produce promesas a partir de una cadena url. Así que
T' : string
, yT : promise
. Y de lo que dijimos antespromise : Observable<T''>
, asíT : Observable<T''>
, conT'' : html
. si pones esa función promise producing enmap
, 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 demap
. Dependiendo de su antecedentes, esto podría ser chino para usted, pero todo se volvió claro para mí con la información de escritura y el dibujo de aquí :http://reactivex.io/documentation/operators/flatmap.html
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-22 04:19:41
['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]]
Se usa flatMap cuando se tiene un Observable cuyos resultados son más Observables.
Si tiene un observable que es producido por otro observable, no puede filtrarlo, reducirlo o mapearlo directamente porque tiene un Observable no los datos. Si produce un observable, elija flatMap sobre map; entonces está bien.
Al igual que en el segundo fragmento, si está haciendo una operación asincrónica, debe usar Mapa plano.
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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-20 00:45:48
flatMap
transformar los elementos emitidos por un Observable en nuevos Observables, luego aplana las emisiones de esos en un solo Observable.
Echa un vistazo al siguiente escenario donde get("posts")
devuelve un Observable que está "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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-04 02:00:42
No es una matriz de matrices. Es un observable de observable (s).
Lo siguiente devuelve un flujo observable de cadena.
requestStream
.map(function(requestUrl) {
return requestUrl;
});
Mientras que esto devuelve un flujo observable de flujo observable de json
requestStream
.map(function(requestUrl) {
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
});
flatMap
aplana el observable automáticamente para nosotros para que podamos observar el flujo json directamente
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-08 09:51:25
Un Observable es un objeto que emite una secuencia de eventos: Siguiente, Error y Completado.
Cuando su función devuelve un Observable, no devuelve un flujo, sino una instancia de Observable. El operador flatMap
simplemente asigna esa instancia a una secuencia.
Ese es el comportamiento de flatMap
cuando se compara con map
: Ejecuta la función dada y aplana el objeto resultante en una secuencia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-02 07:51:11
Simple:
[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]]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-31 23:05:27
La gente tiende a complicar las cosas dando la definición que dice:
FlatMap transforma los elementos emitidos por un Observable en Observables, a continuación, aplanar las emisiones de los mismos en un solo Observable
Juro que esta definición todavía me confunde, pero voy a explicarla de la manera más simple, que es usando un ejemplo
Nuestra situación : tenemos un observable que devuelve datos (URL simple) que vamos a úselo 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
Así que como se puede ver no podemos llegar a los datos que necesitamos directamente por lo que la primera forma de recuperar los datos que podemos utilizar sólo 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. esto actualmente no se ve mal, pero imagine que tenemos 10 suscripciones anidadas que se convertirían en inalcanzable.
Así que una mejor manera de manejar esto es 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));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-28 18:11:06
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 Mapa plano
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)})
})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-18 11:14:33
Aquí para mostrar la implementación equivalente de un mapa plano utilizando subscribes.
Sin Mapa plano:
this.searchField.valueChanges.debounceTime(400)
.subscribe(
term => this.searchService.search(term)
.subscribe( results => {
console.log(results);
this.result = results;
}
);
);
Con Mapa plano:
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.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-11 13:06:22