Skip to content
On this page

Comment utiliser concatMap sur RxJS ?

Voici un exemple:

javascript
import { interval, timer,  take, concatMap, map } from 'rxjs';

const source = interval(50).pipe(take(5)); 
const result = source.pipe(
  concatMap(value => 
    timer(Math.random() * 1000).pipe(map(() => value))
  )
);

result.subscribe(
  message => console.log(message),
  error => console.error('Erreur :', error),
  () => console.log('Toutes les opérations sont terminées')
);

Explication du code

  1. 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).
  2. Utilisation de concatMap :

    • concatMap est utilisé pour transformer chaque valeur émise par source en un nouvel observable.
    • La fonction de projection crée un timer qui attend un temps aléatoire (jusqu'à 1000 millisecondes) avant d'émettre la valeur.
  3. Souscription :

    • On souscrit à result pour afficher chaque valeur une fois que le timer 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é.

Intérêt de concatMap

L'intérêt principal de concatMap dans ce contexte est d'assurer que les opérations asynchrones (ici, les temporisations aléatoires avec timer) sont exécutées séquentiellement et dans l'ordre des valeurs émises par source.

Points clés de concatMap :

  • Séquence d'exécution : concatMap garantit que chaque nouvelle valeur n'est traitée qu'après que l'observable précédent a complété son émission. Même si les valeurs sont émises toutes les 50 millisecondes par interval, les timers introduits par timer sont exécutés de manière séquentielle.

  • Ordre préservé : Les valeurs sont émises dans l'ordre exact où elles ont été reçues par concatMap. Ceci est important pour maintenir l'ordre des opérations asynchrones, évitant des interférences ou des exécutions en parallèle qui pourraient déstructurer l'ordre initial.

Comparaison avec d'autres opérateurs

  • mergeMap : Si vous utilisiez mergeMap à la place de concatMap, les timers seraient exécutés en parallèle. Les valeurs pourraient être émises dans un ordre différent de celui dans lequel elles ont été émises par source.

  • switchMap : Utiliser switchMap annulerait le timer en cours dès qu'une nouvelle valeur est émise, ne permettant pas d'attendre la fin du timer précédent avant de commencer un nouveau.

Bien sûr ! Prenons un autre exemple pour illustrer l'utilisation de concatMap dans un contexte différent.

Exemple de téléchargement séquentiel de fichiers

Imaginez que vous avez une liste de fichiers à télécharger et que vous voulez vous assurer que chaque fichier est téléchargé séquentiellement.

Voici comment vous pouvez utiliser concatMap pour gérer cela :

javascript
import { from, concatMap, ajax } from 'rxjs';

// Liste des URLs de fichiers à télécharger
const fileUrls = [
  'https://example.com/file1',
  'https://example.com/file2',
  'https://example.com/file3'
];

// Observable émettant les URLs de fichiers
const filesObservable = from(fileUrls);

// Fonction qui retourne un observable représentant une requête de téléchargement de fichier
const downloadFile = (url) => ajax.getJSON(url);

// Utilisation de concatMap pour gérer les téléchargements séquentiellement
const result = filesObservable.pipe(
  concatMap(url => {
    console.log(`Téléchargement du fichier : ${url}`);
    return downloadFile(url);
  })
);

// Souscription au résultat pour afficher les données de chaque fichier
result.subscribe(
  data => console.log('Données du fichier téléchargé :', data),
  error => console.error('Erreur de téléchargement :', error),
  () => console.log('Tous les fichiers ont été téléchargés')
);

Cas d'utilisation

TitreDescription
Téléchargement séquentielTélécharge une liste de fichiers séquentiellement, en attendant que chaque téléchargement se termine avant de commencer le suivant.
Opérations retardéesGère des tâches avec des délais aléatoires, assurant une exécution séquentielle pour chaque tâche retardée.
Traitement de tâches par lotsTraite des tâches par lots, en veillant à ce qu'un lot de tâches soit terminé avant de commencer le suivant.
Envoi de messagesEnvoie des messages à une file d'attente ou à un serveur, en s'assurant qu'un message est complètement envoyé avant d'envoyer le suivant.
Mise à jour de base de donnéesEffectue des mises à jour séquentielles dans une base de données, garantissant qu'une mise à jour est terminée avant de commencer la suivante.
Animation séquentielleEnchaîne des animations, s'assurant qu'une animation se termine avant de commencer la suivante.
Lecture séquentielle de fichiersLit des fichiers séquentiellement, garantissant qu'une lecture de fichier se termine avant de commencer la suivante.
Appels API séquentielsEffectue des appels API de manière séquentielle, s'assurant que chaque appel API est complété avant de commencer le suivant.
Traitement séquentiel de formulairesTraite les soumissions de formulaires séquentiellement, garantissant que chaque soumission est traitée avant de passer à la suivante.
Gestion de flux de tâchesGère un flux de tâches où chaque tâche doit être complétée avant de passer à la suivante, assurant une gestion ordonnée des tâches.