Skip to content

switchAll - Basculer vers le nouvel Observable interne

L'opérateur switchAll reçoit un Higher-order Observable (Observable d'Observables) et bascule immédiatement vers le nouvel Observable interne à chaque émission, annulant l'ancien.

Syntaxe de base et utilisation

ts
import { fromEvent, interval } from 'rxjs';
import { map, switchAll, take } from 'rxjs';

const clicks$ = fromEvent(document, 'click');

// Démarre un nouveau compteur à chaque clic (Higher-order Observable)
const higherOrder$ = clicks$.pipe(
  map(() => interval(1000).pipe(take(3)))
);

// Bascule vers le nouveau compteur (annule l'ancien)
higherOrder$
  .pipe(switchAll())
  .subscribe(x => console.log(x));

// Sortie (avec 3 clics):
// 0 (1er compteur)
// 1 (1er compteur)
// ← clic ici (1er annulé)
// 0 (2ème compteur) ← bascule vers le nouveau compteur
// ← clic ici (2ème annulé)
// 0 (3ème compteur) ← bascule vers le nouveau compteur
// 1 (3ème compteur)
// 2 (3ème compteur)
  • Bascule immédiatement quand un nouvel Observable interne est émis par le Higher-order Observable
  • L'Observable interne précédent est automatiquement annulé
  • Seul le dernier Observable interne est toujours en cours d'exécution

Documentation officielle RxJS - switchAll

Patterns d'utilisation typiques

  • Fonctionnalité de recherche (annuler l'ancienne recherche à chaque nouvelle saisie)
  • Autocomplétion
  • Mises à jour de données en temps réel (basculer vers la dernière source de données)

Exemple de code pratique

Un exemple qui annule l'ancienne recherche et exécute uniquement la dernière à chaque nouvelle saisie

ts
import { fromEvent, of } from 'rxjs';
import { map, switchAll, debounceTime, delay } from 'rxjs';

const input = document.createElement('input');
input.placeholder = 'Entrez un mot-clé de recherche';
document.body.appendChild(input);

const output = document.createElement('div');
document.body.appendChild(output);

let searchCount = 0;

// Debounce des événements de saisie
const search$ = fromEvent(input, 'input').pipe(
  debounceTime(300),
  map((e) => (e.target as HTMLInputElement).value)
);

// Higher-order Observable: appel API de recherche simulé pour chaque valeur de saisie
const results$ = search$.pipe(
  map(query => {
    const id = ++searchCount;
    const start = Date.now();

    // Appel API de recherche simulé (délai de 1 seconde)
    return of(`Résultats de recherche: "${query}"`).pipe(
      delay(1000),
      map(msg => {
        const elapsed = ((Date.now() - start) / 1000).toFixed(1);
        return `[Recherche#${id}] ${msg} (${elapsed}s)`;
      })
    );
  }),
  switchAll() // Annule l'ancienne recherche quand une nouvelle commence
);

results$.subscribe(result => {
  output.innerHTML = ''; // Efface le résultat précédent
  const item = document.createElement('div');
  item.textContent = result;
  output.appendChild(item);
});
  • Quand l'utilisateur modifie la saisie, l'ancienne recherche est automatiquement annulée
  • Seul le dernier résultat de recherche est affiché

Opérateurs associés

OpérateurDescription
switchMapRaccourci pour map + switchAll (le plus couramment utilisé)
mergeAllSouscrit à tous les Observables internes en parallèle
concatAllSouscrit aux Observables internes séquentiellement (attend la complétion)
exhaustAllIgnore les nouveaux Observables internes pendant l'exécution

Points d'attention

Prévention des fuites mémoire

switchAll annule automatiquement les anciens Observables internes, ce qui aide à prévenir les fuites mémoire. C'est idéal pour les cas où de nouvelles requêtes sont fréquentes, comme la recherche ou l'autocomplétion.

Observables internes qui ne se terminent pas

Même si les Observables internes ne se terminent pas, ils basculent automatiquement quand un nouveau est émis.

ts
// interval ne se termine pas, mais est automatiquement annulé au prochain clic
clicks$.pipe(
  map(() => interval(1000)), // Ne se termine pas
  switchAll()
).subscribe();

Optimal quand seule la dernière valeur compte

Utilisez switchAll quand le résultat de l'ancien traitement n'est pas nécessaire et que seul le dernier résultat compte. Si tous les résultats sont nécessaires, utilisez mergeAll.

Publié sous licence CC-BY-4.0.