yield en JavaScript : mettre une fonction en pause et la reprendre plus tard

Le mot-clé yield rend une valeur depuis une fonction génératrice puis met son exécution en pause. Fonctionnement, délégation avec yield* et usages réels.
3 min de lecture
Believemy logo

Une fonction ordinaire va jusqu'au bout : elle démarre, calcule, rend un résultat, et son travail est terminé. Une fonction génératrice, elle, sait s'arrêter au milieu, rendre une valeur, et attendre qu'on lui demande la suite.

yield est le mot-clé qui marque ces points d'arrêt. C'est la seule construction du langage qui permette à une fonction de garder ses variables locales entre deux appels sans les stocker ailleurs.


Définition

yield rend une valeur au code appelant et met en pause la fonction génératrice qui le contient, dont l'exécution reprendra exactement à cette ligne au prochain appel de next().

Une fonction génératrice se déclare avec une étoile : function* nom(). L'appeler n'exécute rien, cela crée un itérateur, un objet muni d'une méthode next().

JAVASCRIPT
function* compteur() {
  yield 1;
  yield 2;
  return 'fini';
}

const it = compteur();
it.next(); // { value: 1, done: false }
it.next(); // { value: 2, done: false }
it.next(); // { value: 'fini', done: true }
it.next(); // { value: undefined, done: true }

Chaque appel renvoie un objet à deux clés : la valeur rendue, et un drapeau qui indique si la fonction est arrivée au bout.


Ce que yield n'est pas

Mot-cléEffet sur la fonctionReprise possible
returnTermine définitivementNon
yieldMet en pauseOui, au prochain next()
awaitMet en pause jusqu'à une promesseAutomatique

À noter : la valeur passée à return ferme la série mais n'en fait pas partie. Un Spread (...) sur ce générateur donne [1, 2], sans le 'fini'.


Suites infinies et délégation

Comme rien n'est calculé avant qu'on le demande, une fonction génératrice peut décrire une suite sans fin sans jamais saturer la mémoire.

JAVASCRIPT
function* identifiants() {
  let n = 1;
  while (true) yield n++;
}

const ids = identifiants();
ids.next().value; // 1
ids.next().value; // 2

L'étoile sert aussi à déléguer : yield* passe la main à un autre générateur, ou à n'importe quelle valeur parcourable, et rend toutes ses valeurs avant de continuer.

JAVASCRIPT
function* interieur() {
  yield 'a';
  yield 'b';
}

function* exterieur() {
  yield 'debut';
  yield* interieur();
  yield 'fin';
}

[...exterieur()]; // ['debut', 'a', 'b', 'fin']
Bon à savoir

La communication va dans les deux sens. La valeur passée à next() devient le résultat du yield en attente, ce qui permet d'écrire une fonction qui pose une question, se met en pause, et reprend avec la réponse.


Questions fréquentes

Question

À quoi cela sert-il concrètement ?

Aux séquences dont on ne veut pas calculer tous les éléments d'avance : pagination d'une API, lecture d'un très gros fichier morceau par morceau, identifiants uniques. Un générateur produit ce qu'on lui demande, quand on le lui demande, là où un Array (tableau) exigerait de tout construire d'abord.


Question

Peut-on écrire yield hors d'une fonction génératrice ?

Non, le fichier ne se charge pas : le mot-clé n'a de sens que dans une fonction déclarée avec une étoile. La même erreur arrive souvent en le plaçant dans une fonction fléchée imbriquée, qui ne peut pas être génératrice.


Question

Faut-il maîtriser les générateurs pour travailler en JavaScript ?

On en écrit rarement à la main, mais on en croise : les itérateurs asynchrones, parcourus avec for await, reposent dessus, et certaines bibliothèques de gestion d'état les utilisent pour décrire des enchaînements. Savoir lire un function* suffit largement avant d'avoir à en écrire un.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.