Je commence à utiliser RxJS et je ne comprends pas pourquoi, dans cet exemple, nous devons utiliser une fonction comme flatMap
ou concatAll
; où est le tableau de tableaux ici?
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 quelqu'un peut expliquer visuellement ce qui se passe, ce sera très utile.
Quand j'ai commencé à regarder Rxjs
j'ai aussi trébuché sur cette pierre. Ce qui m'a aidé est le suivant:
flatMap
: http://reactivex.io/documentation/operators/flatmap.htmlflatMap
, vous devez plutôt regarder mergeMap
(un autre nom).enfin en regardant les informations de type de RxJava. Javascript n'est pas dactylographié n'aide pas ici. Fondamentalement, si Observable<T>
désigne un objet observable qui transmet des valeurs de type T, alors flatMap
prend une fonction de type T' -> Observable<T>
comme argument et renvoie Observable<T>
. map
prend une fonction de type T' -> T
et renvoie Observable<T>
.
Pour revenir à votre exemple, vous avez une fonction qui produit des promesses à partir d’une chaîne d’URL. Donc, T' : string
et T : promise
. Et d'après ce que nous avons dit avant promise : Observable<T''>
, donc T : Observable<T''>
, avec T'' : html
. Si vous mettez cette fonction de production de promesse dans map
, vous obtenez Observable<Observable<T''>>
lorsque ce que vous voulez est Observable<T''>
: vous voulez que l'observable émette les valeurs html
. flatMap
s'appelle comme ça car elle aplatit (supprime un calque observable) le résultat de map
. En fonction de vos antécédents, cela pourrait être chinois pour vous, mais tout est devenu clair pour moi avec les informations de frappe et le dessin d’ici: http://reactivex.io/documentation/operators/flatmap.html .
['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]]
Vous utilisez flatMap lorsque vous avez un observable dont les résultats sont plus observables.
Si vous avez un observable qui est produit par un autre observable, vous ne pouvez pas le filtrer, le réduire ou le mapper directement car vous avez un observable, pas les données. Si vous produisez un observable, choisissez flatMap sur map; alors tu vas bien.
Comme dans le deuxième extrait, si vous effectuez une opération asynchrone, vous devez utiliser 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>
flatMap
transforme les éléments émis par un observable en nouveaux observables, puis aplatit les émissions de ceux-ci en un seul observable.
Découvrez le scénario ci-dessous où get("posts")
renvoie un observable "aplati" par 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.
Les gens ont tendance à trop compliquer les choses en donnant la définition qui dit:
flatMap transforme les éléments émis par un observable en observables, puis les aplatit en un seul observable
Je jure que cette définition me trouble encore, mais je vais l'expliquer de la manière la plus simple, c'est-à-dire en utilisant un exemple.
Notre situation: nous avons un observable qui renvoie des données (une simple URL) que nous allons utiliser pour passer un appel HTTP qui renverra un observable contenant les données dont nous avons besoin afin que vous puissiez visualiser la situation de la sorte :
Observable 1
|_
Make Http Call Using Observable 1 Data (returns Observable_2)
|_
The Data We Need
comme vous pouvez le constater, nous ne pouvons pas accéder directement aux données dont nous avons besoin. Le premier moyen de récupérer les données consiste à utiliser uniquement des abonnements normaux, comme ceci:
Observable_1.subscribe((URL) => {
Http.get(URL).subscribe((Data_We_Need) => {
console.log(Data_We_Need);
});
});
cela fonctionne, mais comme vous pouvez le constater, nous devons imbriquer des abonnements pour obtenir nos données. Pour le moment, cela n’a pas l’air mauvais, mais imaginons que nous ayons 10 abonnements imbriqués qui ne pourraient plus être maintenus.
une meilleure façon de gérer cela consiste donc simplement à utiliser l'opérateur flatMap
qui fera la même chose mais nous évite cet abonnement imbriqué:
Observable_1
.flatMap(URL => Http.get(URL))
.subscribe(Data_We_Need => console.log(Data_We_Need));
Ce n'est pas un tableau de tableaux. C'est un observable de observable (s).
Ce qui suit renvoie un flux observable de chaîne.
requestStream
.map(function(requestUrl) {
return requestUrl;
});
Bien que cela retourne un flux observable de flux observable de json
requestStream
.map(function(requestUrl) {
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
});
flatMap
aplatit automatiquement l'observable pour que nous puissions observer directement le flux json
Facile:
[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 est un objet qui émet un flux d'événements: Next, Error et Completed.
Lorsque votre fonction renvoie un observable, il ne renvoie pas un flux, mais une instance de observable. L'opérateur flatMap
mappe simplement cette instance sur un flux.
C'est le comportement de flatMap
par rapport à map
: Exécuter la fonction donnée et aplatir l'objet résultant dans un flux.
Ici pour montrer l'implémentation équivalente d'une flatMap en utilisant subscribe.
Sans flatMap:
this.searchField.valueChanges.debounceTime(400)
.subscribe(
term => this.searchService.search(term)
.subscribe( results => {
console.log(results);
this.result = results;
}
);
);
Avec 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
J'espère que ça pourrait aider.
Olivier.
Avec 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)})
Sans flatMap
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)})
})