AbortController : la technique discrète de nettoyage indispensable à toute application

La plupart des applications frontend exécutent discrètement des opérations asynchrones obsolètes bien après leur utilité. Lorsqu'un utilisateur change de page, un composant se démonte ou une nouvelle requête arrive, d'anciennes requêtes réseau continuent de s'exécuter et peuvent écraser les données fraîches avec des résultats périmés. React affiche un avertissement — « Impossible d'effectuer une mise à jour d'état sur un composant démonté » — tandis que le JavaScript vanilla livre simplement de mauvaises données sans aucun indice. Une fonctionnalité simple des navigateurs, appelée AbortController, règle ce problème, et elle est largement prise en charge depuis 2018.
La condition de course que vous ignoriez
Imaginez que vous tapiez « re » puis « rea » avant que la première recherche ne se termine. Deux appels fetch se disputent sur le réseau. La requête la plus ancienne pour « re » pourrait se terminer après la nouvelle pour « rea », écrasant les résultats corrects avec des données obsolètes. Aucun message d'erreur ne s'affiche, aucun avertissement — simplement une interface utilisateur incorrecte. Ce n'est pas théorique : cela arrive sur des réseaux lents, lors de frappes rapides ou en staging juste avant une démo.
Trois lignes pour mettre fin à la course
AbortController associe un objet contrôleur à un signal. Vous transmettez le signal à fetch et appelez abort() pour annuler. Dans un useEffect de React, créez le contrôleur en haut, passez { signal: controller.signal } à fetch, et retournez une fonction de nettoyage qui appelle controller.abort(). Lorsque la requête change ou que le composant se démonte, la fonction de nettoyage s'exécute en premier — annulant l'ancienne requête avant qu'elle ne puisse mettre à jour l'état. La nouvelle requête démarre alors à zéro avec un nouveau contrôleur.
useEffect(() => {
const controller = new AbortController();
fetch(/api/search?q=${query}, { signal: controller.signal })
.then(r => r.json())
.then(data => setResults(data))
.catch(err => {
if (err.name !== 'AbortError') throw err;
});
return () => controller.abort();
}, [query]);
Gérer les annulations avec élégance
Lorsqu'une requête est annulée, elle rejette avec une erreur nommée « AbortError ». Ignorer ce cas déclenche votre boundary d'erreur à chaque démontage. Traitez-le comme une sortie normale : interceptez-le, vérifiez son nom et laissez-le passer silencieusement. La même règle s'applique avec async/await.
useEffect(() => {
const controller = new AbortController();
async function load() {
try {
const res = await fetch(/api/search?q=${query}, { signal: controller.signal });
const data = await res.json();
setResults(data);
} catch (err) {
if (err instanceof Error && err.name === 'AbortError') return;
throw err;
}
}
load();
return () => controller.abort();
}, [query]);
Adopter AbortController représente une modification minime aux retombées majeures : moins de rendus obsolètes, des journaux plus silencieux et un comportement plus prévisible dans toutes les conditions réseau.
Source : DEV Community. Synthèse éditoriale assistée par IA — TechnoExpress.

