W3docs

Itérateurs et générateurs asynchrones en JavaScript

Apprenez les itérateurs async et générateurs async en JavaScript : Symbol.asyncIterator, async function*, for await...of avec des exemples pratiques.

La programmation asynchrone est une pierre angulaire du développement JavaScript moderne, permettant aux développeurs d'écrire du code non bloquant et concurrent qui peut gérer efficacement des tâches telles que les requêtes réseau, les E/S de fichiers et les minuteries. Ce guide couvre les itérateurs asynchrones et les générateurs asynchrones, deux fonctionnalités introduites dans ECMAScript 2018 qui permettent d'itérer sur des données arrivant au fil du temps — un fragment par aller-retour réseau, un événement par action utilisateur — sans bloquer le reste de votre programme.

Cette page suppose que vous êtes à l'aise avec les itérables, les générateurs et les promesses classiques. Si l'un de ces sujets vous est inconnu, lisez-le d'abord.

Comprendre les itérateurs asynchrones

Que sont les itérateurs asynchrones ?

Les itérateurs asynchrones sont un type spécial d'itérateur conçu pour gérer les flux de données asynchrones. Contrairement aux itérateurs traditionnels, qui fonctionnent de manière synchrone, les itérateurs asynchrones permettent aux développeurs d'itérer sur des séquences de valeurs asynchrones, telles que des promesses ou des flux, de manière non bloquante.

Techniquement, un object est considéré comme un itérable asynchrone s'il implémente la méthode Symbol.asyncIterator, qui retourne un object itérateur asynchrone. Voici un exemple pratique d'implémentation manuelle de cette interface sur un object personnalisé :

javascript— editable

Itérateurs synchrones vs. itérateurs asynchrones

La différence entre un itérable classique et un itérable asynchrone se résume à trois points : le nom de la méthode, le type de retour de next(), et la boucle utilisée pour le consommer.

Itérable synchroneItérable asynchrone
MéthodeSymbol.iteratorSymbol.asyncIterator
next() retourne{ value, done }une Promise de { value, done }
Boucle de consommationfor...offor await...of
Syntaxe de générateurfunction*async function*

Parce que next() retourne une Promise dans le cas asynchrone, chaque étape de la boucle peut attendre une opération asynchrone — un fetch, une minuterie, une lecture de base de données — avant que la valeur suivante soit produite. Un simple for...of ne peut pas faire cela : il s'attend à ce que value/done soit disponible immédiatement. Utiliser for await...of sur un itérable synchrone fonctionne quand même (le moteur enveloppe les valeurs dans des promesses résolues), mais utiliser un for...of synchrone sur un itérable asynchrone ne fonctionne pas — vous itéreriez simplement sur des objets Promise en attente.

Comment utiliser les itérateurs asynchrones

Pour exploiter les itérateurs asynchrones dans votre code JavaScript, vous devez d'abord comprendre leurs concepts fondamentaux et leur syntaxe. Explorons un exemple simple pour démontrer leur fonctionnement en pratique :

javascript— editable

Dans cet exemple, nous définissons une fonction génératrice asynchrone generateNumbers() qui produit une séquence de nombres de manière asynchrone. Nous créons ensuite un itérable asynchrone à partir de la fonction génératrice et utilisons une boucle for await...of pour itérer sur les valeurs produites par l'itérateur asynchrone.

Remarque : Lorsque vous utilisez yield avec une valeur simple à l'intérieur d'une async function*, la méthode next() de l'itérateur retourne automatiquement une Promise qui se résout en { value: <votre valeur>, done: false }. Vous n'avez besoin d'utiliser yield explicitement sur une Promise que si vous souhaitez que le consommateur reçoive un object Promise plutôt que la valeur résolue.

Applications concrètes des itérateurs asynchrones

Les itérateurs asynchrones sont largement utilisés dans les scénarios impliquant le traitement de données asynchrones, comme la récupération de données depuis des API externes, la lecture de flux, ou la gestion d'événements asynchrones. Leur polyvalence et leur efficacité en font des outils indispensables pour les développeurs JavaScript modernes qui souhaitent créer des applications évolutives et réactives.

Explorer les générateurs JavaScript

Introduction aux générateurs

Les générateurs sont une fonctionnalité puissante introduite dans ECMAScript 2015 qui permet la création de séquences itérables avec une logique d'itération personnalisée. Contrairement aux fonctions traditionnelles, qui s'exécutent jusqu'à leur achèvement lors de leur invocation, les générateurs peuvent mettre en pause et reprendre leur exécution, permettant une évaluation paresseuse des valeurs.

Il est important de distinguer les générateurs standard des générateurs asynchrones :

  • Générateurs standard (function*) : Produisent des valeurs de manière synchrone.
  • Générateurs asynchrones (async function*) : Retournent une Promise depuis chaque appel à next(), permettant au consommateur d'attendre chaque valeur en utilisant for await...of.

Utiliser les générateurs pour la programmation asynchrone

L'un des cas d'utilisation les plus convaincants des générateurs est la programmation asynchrone. En combinant les générateurs avec des promesses, les développeurs peuvent créer des flux de travail asynchrones à la fois élégants et faciles à raisonner. Voici un exemple moderne d'utilisation d'un générateur asynchrone pour récupérer et produire des données depuis un serveur distant :

javascript— editable

Dans cet exemple, nous définissons une fonction génératrice asynchrone fetchTodos() qui récupère des données de manière asynchrone depuis une API distante en utilisant la fonction fetch(). En utilisant await à l'intérieur du générateur et en produisant les éléments un par un, nous pouvons diffuser les résultats directement dans une boucle for await...of sans appels manuels à .next() ni chaînage de promesses.

Récupération paginée avec un générateur asynchrone

Le pattern qui met en valeur les générateurs asynchrones est la pagination paresseuse. De nombreuses API retournent des résultats en pages et attendent que vous continuiez à demander la page suivante jusqu'à ce qu'il n'y en ait plus. Un générateur asynchrone peut masquer toute cette gestion interne : il récupère une page, produit ses éléments un par un, et ne demande la page suivante que lorsque le consommateur en a besoin. L'appelant peut s'arrêter tôt — par exemple après avoir trouvé ce dont il a besoin — et aucune autre requête réseau n'est effectuée.

javascript— editable

Remarquez le break : comme le générateur est paresseux, quitter la boucle après 25 éléments signifie que le générateur ne demande jamais la page 3. C'est ce qui distingue un générateur asynchrone de la récupération de tout en avance dans un array — vous ne payez que pour les données que vous utilisez réellement.

Patterns avancés avec les générateurs

Les générateurs offrent une multitude de patterns et de techniques avancés pour résoudre des problèmes de programmation complexes. Voici quelques exemples illustrant leur polyvalence :

  • Exécution parallèle : En initiant plusieurs générateurs et en gérant leurs promesses de manière concurrente, vous pouvez effectuer plusieurs tâches asynchrones simultanément.
  • Gestion des erreurs : Utilisez des blocs try-catch à l'intérieur des générateurs pour gérer élégamment les promesses rejetées produites pendant le processus d'itération.
  • Pipelines de données : Construisez des pipelines de traitement de données en chaînant des générateurs, où la sortie d'un générateur sert d'entrée pour le suivant.
javascript— editable

Conclusion

En conclusion, les itérateurs asynchrones et les générateurs sont des outils indispensables dans l'arsenal du développeur JavaScript moderne. En maîtrisant ces fonctionnalités puissantes, vous pouvez débloquer de nouvelles dimensions d'expressivité et d'efficacité dans votre code asynchrone. Que vous construisiez des applications web, des API côté serveur ou des utilitaires en ligne de commande, les itérateurs asynchrones et les générateurs vous permettent de relever des défis asynchrones complexes avec aisance. Commencez dès aujourd'hui à intégrer les itérateurs asynchrones et les générateurs dans vos projets JavaScript et élevez vos compétences de programmation vers de nouveaux sommets !

Sujets connexes

  • Itérables — la base synchrone derrière for...of et Symbol.iterator.
  • Générateurs — la syntaxe function* sur laquelle s'appuient les générateurs asynchrones.
  • Promesses — ce que chaque await à l'intérieur d'un générateur asynchrone résout.
  • Async/await — la syntaxe avec laquelle for await...of est associée.

Practice

Pratique
Qu'est-ce qui est vrai concernant les itérateurs et générateurs asynchrones de JavaScript ?
Qu'est-ce qui est vrai concernant les itérateurs et générateurs asynchrones de JavaScript ?
Was this page helpful?