J'apprends RxJS en lisant ce tutoriel http://reactive-extensions.github.io/learnrx/
.
J'ai du mal à comprendre la méthode map de Observable
. La version Array
de map
est vraiment simple et directe. Je n'ai aucune idée de ce que signifie exactement le map
dans le cas d'un Observable
(et pourquoi a-t-il un alias nommé select
?!).
Voici ce que la documentation m'a dit. Cela pourrait ne pas être utile pour la plupart des débutants ...
Projette chaque élément d'une séquence observable dans une nouvelle forme en incorporant l'index de l'élément. Il s'agit d'un alias pour la méthode select.
Je ne comprends pas map
dans le contexte de event
. Par exemple, le code ci-dessous fonctionne exactement ce que j'attendais. J'ai pensé à ce morceau de code comme: "Écoutez le click-event
à partir du flux d'événements de #btn
".
var btnClicks, observable;
btnClicks = Rx.Observable.fromEvent($('#btn'), "click");
observable = btnClicks.subscribe(function(e) {
console.log(e);
});
Mais que se passe-t-il quand il s'agit de cela ??
var btn2Clicks, btnClicks, observable;
btnClicks = Rx.Observable.fromEvent($('#btn'), "click");
btn2Clicks = Rx.Observable.fromEvent($('#btn2'), "click");
observable = btnClicks.map(function(e) {
return btn2Clicks;
}).subscribe(function(e) {
console.log(e);
});
Ce que je pensais, c'était utiliser le map
pour transformer une collection d'un click-event en une autre collection de event-collection. Le filter
est facile à comprendre, tout comme le mot filter
signifie, prenez l'événement seul qui m'intéresse et ignorez les autres. Mais qu'en est-il du map
dans le contexte de event
? Si cela signifie "transformer une collection en une autre" tout comme la version du tableau, pourquoi elle se déclenche toujours lorsque #btn
cliqué ??
Je veux dire que je l'ai mappé à une autre collection, maintenant ce n'est plus une collection de click-event de #btn
mais c'est une nouvelle collection de quelque chose ... Mais ça se déclenche quand #btn
cliqué qui n'a pas de sens pour moi.
map
fonctionne exactement de la même manière pour Observables que pour les tableaux. Vous utilisez map
pour transformer une collection d'éléments en une collection d'éléments différents. Cela aide si vous considérez un observable comme une collection d'éléments (tout comme un tableau est également une collection d'éléments), du moins du point de vue de l'observateur.
Par exemple, prenez ces 2 méthodes que vous avez écrites pour utiliser avec certains tableaux:
function multiplyByTwo(collection) {
return collection.map(function (value) {
return value * 2;
});
}
function removeZeroes(collection) {
return collection.filter(function (value) {
return value !== 0;
});
}
var a = [1, 2, 3, 4, 0, 5];
var b = multiplyByTwo(a); // a new array [2, 4, 6, 8, 0, 10]
var c = removeZeroes(b); // a new array [2, 4, 6, 8, 10]
Vous pouvez utiliser ces mêmes fonctions pour un observable:
var a = Rx.Observable.of(1, 2, 3, 4, 0, 5);
var b = multiplyByTwo(a); // a new observable [2, 4, 6, 8, 0, 10]
var c = removeZeroes(b); // a new observable [2, 4, 6, 8, 10]
Cela est possible car les observables RxJ implémentent les opérateurs de tableau comme map
et filter
pour avoir exactement la même sémantique que pour les tableaux. Si vous savez comment ils fonctionnent pour les tableaux, vous savez comment ils fonctionnent pour les observables.
Cette astuce est le résultat de la double nature des observables et des énumérables .
Si vous parcourez le didacticiel interactif que vous consultez, il vous guide dans ce processus. Je crois que cela vous démarre en écrivant des opérateurs de carte pour les tableaux, puis dans un didacticiel ultérieur, un observable comme source.
P.S. Il s'agit d'un alias pour select
en raison de son historique: Reactive Extensions a d'abord été implémenté dans .NET puis porté dans d'autres langues. Rx.NET utilise les mêmes opérateurs que ceux utilisés par LINQ de .NET (puisque IObservable
est le double de IEnumerable
). L'opérateur de carte de LINQ est appelé Select
(et son opérateur de filtre est appelé Where
). Ces noms proviennent de l'origine de LINQ. L'un des objectifs de la création de LINQ était de permettre l'écriture de requêtes de base de données en C #. Ainsi, ils ont adopté des conventions de dénomination SQL pour de nombreux opérateurs (LINQ SELECT correspond directement à SQL SELECT, LINQ WHERE correspond à SQL WHERE, etc.).
La carte dans Rxjs utilisée pour la projection signifie que vous pouvez transformer le tableau en un tableau entièrement nouveau. Afin de comprendre le fonctionnement de Map, nous pouvons implémenter notre propre fonction de map en utilisant du javascript simple.
Array.prototype.map = function(projectionFunction){
var results=[];
this.forEach(function(item) {
results.Push(projectionFunction(item));
});
return results;
};
Vous pouvez voir que j'ai écrit une fonction de carte qui accepte une fonction anonyme comme paramètre. Ce sera votre fonction d'appliquer la projection pour transformer le tableau. À l'intérieur de la fonction de carte, vous pouvez voir itérer chaque élément dans un tableau, appeler la fonction de projet en passant chaque élément et enfin le résultat de la fonction de projection sera poussé vers le tableau de résultats.
JSON.stringify([1,2,3].map(function(x){return x+1;}))
Sortie
[2,3,4]