
Dans un chapitre antérieur, vous avez utilisé des opérateurs bas niveau pour toucher directement aux émissions d'un Observable.
Dans ce chapitre, vous allez découvrir les opérateurs haut niveau qui servent à gérer la combinaison des flux, le parallélisme, et le passage d'un flux à un autre.
Qu'est-ce qu'un Observable haut niveau ?
Un Observable haut niveau combine un flux source et des flux secondaires. À chaque émission du flux source, l'Observable haut niveau souscrit à un flux secondaire.
Prenons un exemple :
Flux source : les clics sur un bouton
Flux secondaires : un compte à rebours qui va de 10 à 0.
Si on clique une fois, un compte à rebours est démarré. Jusqu'ici, c'est simple.
Mais qu'est-ce qui se passe lorsqu'on clique une deuxième fois alors que le premier compte à rebours n'a pas terminé ?
Nous avons plusieurs options :
on démarre un autre compte à rebours en parallèle du premier
on attend que le compte à rebours en cours soit terminé avant de lancer le suivant
on annule le compte à rebours en cours pour en lancer tout de suite un autre
on ignore les clics tant qu'il y a un compte à rebours en cours
Pour chacune de ces situations, RxJS nous propose un opérateur. Vous allez maintenant les découvrir, et pour chaque opérateur vous verrez un cas d'usage concret.
Pour chaque émission du flux source,mergeMapsouscrira à un flux secondaire même s'il y a déjà un autre flux secondaire en cours : il permet de paralléliser les flux.
Vous avez un flux qui émet des URL d'images, et vous souhaitez charger chaque image ainsi émise. Puisque l'ordre d'arrivée n'a pas d'importance, vous pouvez utilisermergeMappour générer le flux final d'images.
On pourrait imaginer :
const images$ = urls$.pipe(
mergeMap(url => loadImage(url))
);Contrairement àmergeMap, l'opérateurconcatMapgarantit l'ordre des opérations.
Pour chaque émission du flux source,concatMapattendra la complétion du flux secondaire en cours avant de lancer le suivant.
Vous avez un jeu où l'utilisateur peut cliquer sur différents boutons pour animer un personnage à l'écran. Pour que l'animation reste fluide, il faut attendre la fin de l'animation précédente avant de lancer la suivante. On aurait :
const animations$ = buttonClicks$.pipe(
concatMap(button => createAnimationFor(button))
);Lors de l'arrivée d'une nouvelle émission source, s'il y a une opération secondaire en cours,switchMapl'annule et démarre tout de suite la nouvelle.
Vous avez un champ de texte où vous voulez proposer l'autocomplétion qui communique avec un serveur, c'est-à-dire qu'à chaque fois que l'utilisateur modifie le champ, vous en envoyez le contenu au serveur pour qu'il propose des réponses. Si l'utilisateur modifie le champ lorsqu'une requête est déjà en cours, cette requête ne nous intéresse plus : on veut lancer tout de suite la suivante. Ça donne :
const autoCompleteAnswers$ = textInput$.pipe(
switchMap(text => askServer(text))
);Cet opérateur est le plus simple mais reste indispensable pour certaines situations : lorsqu'une opération secondaire est déjà en cours,exhaustMapignore toute émission source.
Votre application permet de sauvegarder le contenu d'un formulaire. Lorsqu'une sauvegarde est déjà en cours, si l'utilisateur, un peu énervé, clique plusieurs fois sur le bouton sans que le contenu du formulaire ait changé, on n'a aucun intérêt à prendre en compte ces nouveaux clics. On pourrait donc avoir :
const saveRequests$ = clicks$.pipe(
exhaustMap(() => saveFormContent())
);
La page de l'application d'accompagnement (Soyez réactif avec les Observables) qui correspond à ce chapitre contient un outil qui permet de visualiser les différences entre les opérateurs haut niveau.
Dans cet outil :
les clics sur les boutons rouge, vert, et bleu correspondent au flux source : la dernière émission de ce flux s'affiche dans le carré à gauche
le flux secondaire correspond au remplissage de la barre de progression à droite avec la couleur sélectionnée (2500ms)
Pour visualiser le fonctionnement d'un opérateur, sélectionnez-le puis cliquez sur les différents boutons. Vous en verrez le résultat.
Un Observable haut niveau est un Observable qui combine un flux source et des flux secondaires.
Les opérateurs haut niveau servent à gérer les situations où une nouvelle émission arrive de l'Observable source alors que la souscription précédente à l'Observable secondaire n'a pas encore complété :
mergeMapn'attend pas qu'un Observable secondaire complète pour souscrire au suivant – il assure la mise en parallèle.
concatMapattend que l'Observable secondaire complète avant de souscrire au suivant – il assure la mise en série, même lorsque l'Observable source émet plusieurs fois.
exhaustMapignore toute nouvelle émission de l'Observable source tant qu'il y a une souscription active à un Observable secondaire.
LorsqueswitchMapreçoit une nouvelle émission de l'Observable source, s'il y a une souscription active à un Observable secondaire, il l'annule et souscrit au suivant.
Les Observables sont un sujet complexe, et ils ont été abordés ici d'une manière plutôt théorique. Vous découvrirez, au cours des parties suivantes, certains des Observables intégrés dans le framework Angular, et j'espère que cette première partie difficile vous aidera à mieux les apprivoiser, et vous servira de référence à l'avenir tout au long de votre carrière de développeur !
Il est temps pour le quiz — validez ce que vous avez appris dans ce cours !