ES6 a introduit les fonctions génératrices, qui peuvent suspendre le flux d'exécution d'une fonction grâce au mot-clé `yield`, ce qui permet de modifier le flux d'exécution et fournit ainsi une solution pour la programmation asynchrone. Utilisation de base
Composition de fonctions génératrices
Un générateur possède deux parties qui le distinguent des fonctions ordinaires :
-
La première est qu'après `function` et avant le nom de la fonction, il y a un `*` ;
-
À l'intérieur de la fonction, il y a une expression `yield`.
Parmi eux, `*` sert à indiquer que la fonction est une fonction génératrice, et `yield` sert à définir l'état interne de la fonction.
Mécanisme d'exécution
Appeler une fonction génératrice revient au même que d'appeler une fonction ordinaire : il suffit d'ajouter des parenthèses après le nom de la fonction. Cependant, une fonction génératrice ne s'exécute pas immédiatement comme une fonction ordinaire ; au lieu de cela, elle renvoie un pointeur vers un objet d'état interne. Par conséquent, pour appeler la méthode `next` de l'objet itérateur, le pointeur commencera à s'exécuter depuis le début de la fonction ou depuis l'endroit où il s'est arrêté la dernière fois.
Lors du premier appel de la méthode `next`, l'exécution commence au début de la fonction génératrice. D'abord elle affiche `one`, puis s'arrête en atteignant `yield`, et utilise la valeur de l'expression après `yield`, `'1'`, comme propriété `value` de l'objet renvoyé. À ce stade, la fonction n'a pas terminé son exécution, donc la propriété `done` de l'objet renvoyé est `false`.
Lors du deuxième appel de la méthode `next`, c'est la même chose que l'étape précédente.
Lors du troisième appel de la méthode `next`, elle affiche d'abord `three`, puis effectue l'opération de retour de la fonction, et utilise la valeur de l'expression après `return` comme propriété `value` de l'objet renvoyé. À ce stade, la fonction est terminée, donc la valeur de la propriété `done` est `true`.
Lors du quatrième appel de la méthode `next`, la fonction a déjà fini de s'exécuter, donc elle renvoie `undefined` comme valeur de la propriété `value` et `true` comme valeur de la propriété `done`. S'il n'y avait pas d'instruction `return` lors de la troisième étape, elle renverrait directement `{value: undefined, done: true}`.
Méthodes de l'objet itérateur renvoyé par la fonction
méthode `next`
En général, lorsque la méthode `next` est appelée sans arguments, la valeur de retour de l'expression `yield` est `undefined`. Lorsqu'un argument est passé à `next`, cet argument sert de valeur de retour du `yield` précédent.
Appel de `next` sans arguments
En plus d’utiliser `next`, vous pouvez également utiliser une boucle `for...of` pour parcourir l’objet Iterator généré par une fonction génératrice.
méthode `return`
La méthode `return` renvoie la valeur donnée et met fin à l’itération de la fonction génératrice.
Lorsque la méthode `return` reçoit un argument, elle renvoie cet argument ; lorsqu’aucun argument n’est fourni, elle renvoie `undefined`.
L'objet itérateur lève deux erreurs. La première est interceptée à l'intérieur de la fonction Generator. La seconde, parce que le `catch` à l'intérieur du corps de la fonction a déjà été exécuté, ne sera pas interceptée à nouveau, donc cette erreur est levée en dehors du corps de la fonction Generator et interceptée par le `catch` à l'extérieur du corps de la fonction.
Expression `yield*`
L'expression `yield*` signifie que `yield` renvoie un objet itérateur, qui est utilisé pour appeler une autre fonction génératrice à l'intérieur d'une fonction génératrice.
Cas d'utilisation
Implémentation d'un Iterator
Fournit une méthode de parcours pour les objets qui n'ont pas d'interface Iterator.
`Reflect.ownKeys()` renvoie toutes les propriétés d'un objet, que les propriétés soient énumérables ou non, y compris les Symboles.
`jane` ne possède pas nativement d'interface Iterator et ne peut pas être parcouru avec `for...of`. Ici, une fonction Generator est utilisée pour ajouter une interface Iterator, afin que l'objet `jane` puisse être parcouru.