Bienvenue dans la deuxième partie du tutoriel sur les Observables.
Dans la première partie, nous avons vu que les Observables nous permettent de traiter des données synchrones et asynchrones. Aussi, nous avons vu la méthode subscribe() à laquelle nous appliquons notre Observer afin de consulter les données. Enfin dans le dernier exemple, une méthode unsubscribe() qui va nous permettre en tant que Observer d'avoir la possibilité de decider de ne plus écouter les données émises.
Vous l’aurez compris, les Observables sont surtout utilisés dans l’objectif de manipuler de la donnée asynchrone. Nous allons donc essayer de comprendre, comment est-ce que les données reçue peuvent être manipulées.
Prenons un cas concret pour illustrer notre problématique :
Imaginons que nous recevons toutes les lettres de l’alphabet en minuscule (a, b, c…) et que nous souhaitons leur appliquer une transformation : mettre en majuscule (A, B, C…)
// Implementation naïve
const observer = {
next: val => console.log(val),
error: err => console.log(err),
complete: () => console.log('Complete!')
}
const alphabetObservable = {
subscribe: observer => {
const alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
alphabet.forEach(letter => {
const letterCapitalized = letter.toUpperCase()
observer.next(letterCapitalized)
})
observer.complete()
}
}
alphabetObservable.subscribe(observer) // log a b c d …
Plutôt que de simplement appeler la méthode subscribe()
, l’observable pourrait nous donner la possibilité d’appliquer d’autres transformations comme par exemple :
- Transformer les 21 premières lettres aux chiffres équivalents dans la table ASCII
- Transformer les 5 dernières lettres en arabes
- Et autres...
qui donnerait :
alphabetObservable
.transformOnly21FirstLettersToAscii()
.LowerCase()
.transformOnly5LastLettersToArabicCharacter()
.subscribe(observer)
Ces méthodes de transformations(aussi appelés “Operator”) peuvent être coupler dans l’ordre que l’on souhaite. Enfin pour accéder au résultat de notre transformation, nous allons appeler la méthode .subscribe()
et lui appliquer notre observer.
Appliquer ces transformations directement dans la méthode subscribe()
, nous empêchent d’avoir de la flexibilité. Il nous faut donc une nouvelle façon d’implementer nos Observables pour mettre en place nos opérateurs (méthodes de transformations).
Un opérateur est une méthode de l’observable qui est appelée avant la méthode subscribe() pour effectuer une transformation sur la donnée.
Schema d’exploitation d’un Observable sans Opérateur :
Observable —> 1, 2, 3 —> subscribe // Affiche 1, 2, 3
Schema d’exploitation d’un Observable avec Opérateur :
Observable —> 1, 2, 3 —> add10 —> 10, 20, 30 —> subscribe // Affiche 10, 20, 30
L’opérateur add10()
n’échappe pas à la règle : pour accéder aux données de l’Observable, il doit lui-même jouer le rôle de subscribe()
ensuite permettre aux opérateurs qui le suivent de pouvoir accéder à ses données en renvoyant un observable à son tour. (Oui subscribe()
est considéré comme un opérateur lui aussi)
Du code ! Du code :
const observer = {
next: val => console.log(val),
error: err => console.log(err),
complete: () => console.log('Complete!')
}
function createObservable (subscribe) {
return {
subscribe: subscribe
map: function(transformFn) {
const inputObservable = this;
const outputObservable = createObservable(function subscribe(outputObserver) {
inputObservable.subscribe({
next: function (x) {
const y = transformFn(x)
outputObserver.next(y)
},
error: function (err) {
outputObserver.error(err)
},
complete: function() {
outputObserver.complete()
}
})
})
return outputObservable
}
}
}
const arrayObservable = createObservable(function subscribe(observer) {
[1, 2, 3].forEach(val => observer.next(val))
observer.complete()
})
arrayObservable
.map(x => x + 10)
.subscribe(observer)
Nous avons maintenant une fonction
createObservable()
, qui est appelée à chaque fois qu’on a besoin de retourner un Observable avec l’ensemble des opérateurs.
Vous devez être en mesure de pouvoir appliquer toutes les transformations précedemment citées avec alphabetObservable : à vous de jouer ! :p
RxJS repose basiquement ce qu’on vient de voir précédemment avec beaucoup plus d’opérateurs et différents concepts avancés. Si vous souhaitez en savoir plus, je vous invite à vous rendre sur la documentation officielle.
- Présenter le Marble diagram
- Présenter 2-3 Opérateurs