Appearance
Comment utiliser exhaustMap sur RxJS ?
exhaustMap
est un opérateur de RxJS utilisé pour la gestion des flux de données asynchrones. Il est souvent utilisé lorsqu'on veut ignorer les nouvelles émissions d'un observable jusqu'à ce que l'observable en cours se termine.
Voici une explication simple :
javascript
import { interval, timer, take, exhaustMap, map } from 'rxjs';
const source = interval(50).pipe(take(5));
const result = source.pipe(
exhaustMap(value => timer(20))
);
result.subscribe(
message => console.log(message),
error => console.error('Erreur :', error),
() => console.log('Toutes les opérations sont terminées')
);
Description du code
Création de l'observable source :
interval(50)
crée un observable qui émet des valeurs séquentielles (0, 1, 2, 3, 4, ...) toutes les 50 millisecondes.take(5)
limite cette émission à 5 valeurs (0, 1, 2, 3, 4).
Utilisation de
exhaustMap
:exhaustMap
est utilisé pour transformer chaque valeur émise parsource
en un nouvel observabletimer(20)
.timer(20)
crée un observable qui émet une seule valeur après un délai de 20 millisecondes.
Souscription :
- On souscrit à
result
pour afficher chaque valeur une fois que le timer de 20 millisecondes pour cette valeur a terminé. - Une fois que toutes les valeurs ont été traitées, le message "Toutes les opérations sont terminées" est affiché.
- On souscrit à
Intérêt de exhaustMap
L'intérêt principal de exhaustMap
dans ce contexte est d'assurer que chaque nouvelle valeur émise par l'observable source est ignorée tant que l'inner observable précédent n'a pas terminé son émission.
Points clés de exhaustMap
:
Exécution exclusive :
exhaustMap
garantit que si une nouvelle valeur est émise parsource
pendant qu'un inner observable est en cours d'exécution, cette nouvelle valeur sera ignorée. Cela assure qu'aucun observable inner ne sera exécuté en parallèle.Ignorer les valeurs rapides : Si les valeurs émises par
source
sont plus rapides que la durée de l'inner observable (timer(20)
), les valeurs supplémentaires seront ignorées jusqu'à ce que l'inner observable en cours soit terminé.
Fonctionnement avec timer(20)
- Émission rapide : Ici, chaque valeur de
source
est transformée en untimer
qui attend 20 millisecondes. Commeinterval(50)
émet toutes les 50 millisecondes, chaque valeur est prise en compte, car le délai de 20 millisecondes est plus court que l'intervalle de 50 millisecondes. - Aucun événement ignoré : Puisque 20 ms < 50 ms, l'inner observable a toujours le temps de terminer avant que le
source
émette une nouvelle valeur. Donc, aucun événement n'est ignoré dans ce cas spécifique.
Fonctionnement avec un timer plus grand
Si on modifie le timer
pour avoir un délai plus long, par exemple timer(100)
, le comportement change :
javascript
import { interval, timer } from 'rxjs';
import { take, exhaustMap, map } from 'rxjs/operators';
const source = interval(50).pipe(take(5));
const result = source.pipe(
exhaustMap(value => timer(100))
);
result.subscribe(
message => console.log(message),
error => console.error('Erreur :', error),
() => console.log('Toutes les opérations sont terminées')
);
- Émission plus lente : Chaque valeur de
source
est transformée en untimer
qui attend 100 millisecondes. Commeinterval(50)
émet toutes les 50 millisecondes, le délai de 100 millisecondes est plus long que l'intervalle de 50 millisecondes. - Événements ignorés : Puisque 100 ms > 50 ms, le
timer
de l'inner observable n'a pas le temps de se terminer avant quesource
émette une nouvelle valeur. Par conséquent, toutes les valeurs suivantes desource
seront ignorées tant que l'inner observable n'aura pas terminé.
# Exemple avec des clics rapides
Pour montrer un exemple où des clics rapides émettent des requêtes HTTP mais où nous voulons ignorer les clics supplémentaires tant que la requête en cours n'est pas terminée, nous pouvons utiliser exhaustMap
.
Voici comment cela peut être fait :
javascript
import { fromEvent, exhaustMap, ajax } from 'rxjs';
// Sélectionnez le bouton HTML sur lequel les clics seront écoutés
const button = document.getElementById('myButton');
// Observable qui écoute les clics sur le bouton
const clicks = fromEvent(button, 'click');
// Fonction qui retourne un observable représentant une requête HTTP
const makeRequest = () => ajax.getJSON('https://jsonplaceholder.typicode.com/todos/1');
// Utilisation de exhaustMap pour gérer les requêtes de manière à ignorer les clics rapides
const result = clicks.pipe(
exhaustMap(() => makeRequest())
);
// Souscription au résultat pour afficher les données
result.subscribe(
data => console.log('Données reçues :', data),
error => console.error('Erreur :', error),
() => console.log('Requête terminée')
);
Fonctionnement
- L'utilisateur clique sur le bouton, déclenchant un événement de clic.
exhaustMap
capture cet événement et lancemakeRequest
pour effectuer une requête HTTP.- Si l'utilisateur clique à nouveau avant que la requête en cours ne soit terminée, ces clics sont ignorés.
- Une fois la requête terminée, si un nouveau clic se produit, une nouvelle requête est lancée.
Cet exemple illustre parfaitement comment exhaustMap
peut être utilisé pour gérer des opérations asynchrones de manière exclusive, garantissant qu'une nouvelle opération n'est lancée que lorsque la précédente est terminée, même dans le cas de clics rapides successifs.
Résumé
- Ignorer les clics rapides : Si l'utilisateur clique plusieurs fois rapidement,
exhaustMap
ignore les clics supplémentaires tant que la requête en cours n'est pas terminée. - Exécution exclusive : Cela garantit qu'une seule requête HTTP est en cours à la fois, évitant les surcharges de serveur ou les requêtes multiples inutiles.
cas d'utilisation
Titre | Description |
---|---|
Gestion de clics rapides | Ignorer les clics supplémentaires tant que la requête HTTP en cours n'est pas terminée, empêchant les surcharges de requêtes. |
Détection de mouvement | Ignorer les nouvelles valeurs de détection de mouvement tant que le traitement précédent n'est pas terminé, pour éviter les traitements redondants. |
Suivi de position GPS | Ignorer les nouvelles valeurs de position GPS tant que l'actualisation précédente n'est pas terminée, assurant une gestion ordonnée des données de position. |
Envoi de messages de chat | Empêcher l'envoi de nouveaux messages tant que le message précédent n'a pas été confirmé par le serveur, assurant une livraison ordonnée. |
Validation de formulaire | Ignorer les nouvelles tentatives de validation tant que la validation en cours n'est pas terminée, empêchant les requêtes multiples de validation. |
Chargement de données | Empêcher les nouvelles requêtes de chargement de données tant que le chargement précédent n'est pas terminé, pour éviter les conflits de données. |
Lecture de capteurs IoT | Ignorer les nouvelles lectures de capteurs tant que la lecture précédente n'a pas été traitée, assurant une gestion ordonnée des données des capteurs. |
Mises à jour de configuration | Ignorer les nouvelles tentatives de mise à jour de configuration tant que la mise à jour précédente n'est pas terminée, assurant la cohérence des configurations. |
Téléchargement de fichiers | Empêcher les nouveaux téléchargements de fichiers tant que le téléchargement précédent n'est pas terminé, évitant les conflits de ressources. |
Gestion des notifications | Ignorer les nouvelles notifications tant que la notification en cours n'a pas été traitée, pour éviter les surcharges de notifications. |