J'ai entendu parler d'un mot-clé "yield" en JavaScript, mais j'ai trouvé une documentation très pauvre à ce sujet. Quelqu'un peut-il m'expliquer (ou recommander un site qui explique) son utilisation et à quoi il sert?
javascript
yield
keyword
mck89
la source
la source
Réponses:
La documentation MDN est plutôt bonne, OMI.
la source
Réponse tardive, tout le monde est probablement au courant
yield
maintenant, mais une meilleure documentation est arrivée.Adaptation d'un exemple de "Javascript's Future: Generators" de James Long pour la norme officielle Harmony:
C'est un
yield
peu commereturn
: vous récupérez quelque chose.return x
renvoie la valeur dex
, maisyield x
renvoie une fonction, qui vous donne une méthode pour itérer vers la valeur suivante. Utile si vous disposez d'une procédure potentiellement gourmande en mémoire que vous souhaiterez peut-être interrompre pendant l'itération.la source
function* foo(x){
y êtes*
. Que vous en ayez besoin ou non dépend du type d'avenir que vous revenez. Le détail est long: GvR l'explique pour l'implémentation Python , sur laquelle l'implémentation Javascript est modélisée. L'utilisationfunction *
sera toujours correcte, bien que dans certains cas, les frais généraux soient légèrement plus importantsfunction
qu'avecyield
.function *
etyield
et a ajouté l'erreur citée («Une erreur précoce est déclenchée si une expression de rendement ou de rendement * se produit dans une fonction non génératrice»). Mais, l'implémentation originale de Javascript 1.7 dans Firefox ne nécessitait pas le*
. Réponse mise à jour en conséquence. Merci!C'est vraiment simple, c'est comme ça que ça marche
yield
Le mot clé permet simplement de suspendre et de reprendre une fonction à tout moment de manière asynchrone .Prenez cette fonction de générateur simple :
Jusqu'à ce que vous appeliez _process.next (), il n'exécutera pas les 2 premières lignes de code, puis le premier rendement mettra la fonction en pause . Pour reprendre la fonction jusqu'au prochain point de pause ( mot-clé yield ), vous devez appeler _process.next () .
Mais alors que ce rendement effectue des comportements de pause et de reprendre il peut retourner des résultats aussi bien en
{value: any, done: boolean}
fonction de la fonction précédente nous n'émettre aucune valeur. Si nous explorons la sortie précédente, elle affichera la même chose{ value: undefined, done: false }
avec une valeur non définie .Permet de creuser dans le mot clé yield. Facultativement, vous pouvez ajouter une expression et définir affecter une valeur facultative par défaut . (Syntaxe officielle du document)
expression : valeur à renvoyer de la fonction générateur
rv : renvoie la valeur facultative transmise à la méthode next () du générateur
Essayez-le maintenant
Coutumes
Références:
la source
Simplifiant / développant la réponse de Nick Sotiros (qui je pense est génial), je pense qu'il est préférable de décrire comment on pourrait commencer à coder
yield
.À mon avis, le plus grand avantage de l'utilisation
yield
est qu'elle éliminera tous les problèmes de rappel imbriqués que nous voyons dans le code. Il est difficile de voir comment au début, c'est pourquoi j'ai décidé d'écrire cette réponse (pour moi, et j'espère que les autres!)Pour ce faire, il introduit l'idée d'une co-routine, qui est une fonction qui peut s'arrêter / s'arrêter volontairement jusqu'à ce qu'elle obtienne ce dont elle a besoin. En javascript, cela est indiqué par
function*
. Seules lesfunction*
fonctions peuvent utiliseryield
.Voici quelques javascript typiques:
C'est maladroit car maintenant tout votre code (qui doit évidemment attendre cet
loadFromDB
appel) doit être à l'intérieur de ce rappel laid. C'est mauvais pour plusieurs raisons ...})
que vous devez suivre partoutfunction (err, result)
jargon supplémentaireresult
D'un autre côté, avec
yield
, tout cela peut être fait en une seule ligne à l'aide du joli cadre de co-routine.Et maintenant, votre fonction principale cédera si nécessaire quand elle devra attendre que les variables et les choses se chargent. Mais maintenant, pour exécuter cela, vous devez appeler une fonction normale (fonction non coroutine). Un cadre de co-routine simple peut résoudre ce problème de sorte que tout ce que vous avez à faire est d'exécuter ceci:
Et le début est défini (d'après la réponse de Nick Sotiro)
Et maintenant, vous pouvez avoir un beau code qui est beaucoup plus lisible, facile à supprimer et pas besoin de jouer avec les retraits, les fonctions, etc.
Une observation intéressante est que dans cet exemple, il
yield
s'agit en fait d'un mot-clé que vous pouvez mettre avant une fonction avec un rappel.Imprime "Hello World". Ainsi, vous pouvez réellement transformer n'importe quelle fonction de rappel en utilisation
yield
en créant simplement la même signature de fonction (sans le cb) et en retournantfunction (cb) {}
, comme ceci:Si tout va bien avec cette connaissance, vous pouvez écrire du code plus propre et plus lisible qui est facile à supprimer !
la source
function*
est juste une fonction régulière sans rendement?function *
c'est une fonction qui contient du rendement. C'est une fonction spéciale appelée générateur.yield
partout, je suis sûr que cela a plus de sens que les rappels, mais je ne vois pas comment cela est plus lisible que les rappels.Pour donner une réponse complète:
yield
fonctionne de manière similairereturn
, mais dans un générateur.Quant à l'exemple couramment donné, cela fonctionne comme suit:
Mais il y a aussi un deuxième objectif du mot-clé yield. Il peut être utilisé pour envoyer des valeurs au générateur.
Pour clarifier, un petit exemple:
Cela fonctionne, comme la valeur
2
est affectée ày
, en l'envoyant au générateur, après qu'il s'est arrêté au premier rendement (qui est revenu0
).Cela nous permet de faire des trucs vraiment funky. (regarde coroutine)
la source
Il est utilisé pour les générateurs d'itérateurs. Fondamentalement, il vous permet de créer une séquence (potentiellement infinie) en utilisant du code procédural. Voir la documentation de Mozilla .
la source
yield
peut également être utilisé pour éliminer l'enfer de rappel, avec un framework coroutine.la source
Générateur de séquence de Fibonacci utilisant le mot-clé yield.
la source
Yeild
mot-clé dans la fonction javaScript le rend générateur,qu'est-ce qu'un générateur en javaScript?
Ce qui signifie que les générateurs nous aident à travailler de manière asynchrone avec les itérateurs d'aide, Oh maintenant, quels sont les itérateurs de piratage? vraiment?
d'où l'itérateur nous aide-t-il à accéder à un élément à la fois? il nous aide à accéder aux éléments via les fonctions du générateur,
les fonctions génératrices sont celles dans lesquelles nous utilisons des
yeild
mots clés, les mots clés yield nous aident à mettre en pause et à reprendre l'exécution de la fonctionvoici un exemple rapide
permettez-moi d'expliquer brièvement ce qui se passe
vous avez remarqué que l'exécution est suspendue à chaque
yeild
mot clé et nous pouvons y accéder en premieryield
avec l'aide de l'itérateur.next()
cela itère pour tous les
yield
mots clés un par un, puis retourne indéfini lorsqu'il ne reste plus deyield
mots clés dans des mots simples, vous pouvez dire que leyield
mot clé est le point d'arrêt où la fonction s'arrête à chaque fois et ne reprend que lors de l'appel à l'aide de l'itérateurpour notre cas:
_getMeDrink.next()
c'est un exemple d'itérateur qui nous aide à accéder à chaque point d'arrêt en fonctionExemple de générateurs:
async/await
si vous voyez la mise en œuvre de
async/await
vous verrezgenerator functions & promises
sont utilisés pour faire duasync/await
travailveuillez signaler toute suggestion est la bienvenue
la source
Dépendance entre les appels javascript asynchrones.
Un autre bon exemple de la façon dont le rendement peut être utilisé.
la source
Avant d'en savoir plus sur le rendement, vous devez connaître les générateurs. Les générateurs sont créés à l'aide de la
function*
syntaxe. Les fonctions de générateur n'exécutent pas de code mais renvoient à la place un type d'itérateur appelé générateur. Lorsqu'une valeur est donnée à l'aide de lanext
méthode, la fonction générateur continue de s'exécuter jusqu'à ce qu'elle rencontre un mot clé yield. Utiliseryield
vous redonne un objet contenant deux valeurs, l'une est valeur et l'autre est fait (booléen). La valeur peut être un tableau, un objet, etc.la source
Un exemple simple:
la source
J'essaie également de comprendre le mot clé yield. D'après ma compréhension actuelle, dans le générateur, le mot clé yield fonctionne comme un changement de contexte CPU. Lorsque l'instruction yield est exécutée, tous les états (par exemple, les variables locales) sont enregistrés.
En plus de cela, un objet de résultat direct sera retourné à l'appelant, comme {valeur: 0, done: false}. L'appelant peut utiliser cet objet de résultat pour décider de «réveiller» à nouveau le générateur en appelant next () (appeler next () revient à itérer l'exécution).
Une autre chose importante est qu'il peut définir une valeur sur une variable locale. Cette valeur peut être transmise par l'appelant «next ()» lors du «réveil» du générateur. par exemple, it.next ('valueToPass'), comme ceci: "resultValue = yield slowQuery (1);" Tout comme lors du réveil d'une prochaine exécution, l'appelant peut injecter un résultat en cours d'exécution (en l'injectant dans une variable locale). Ainsi, pour cette exécution, il existe deux types d'état:
le contexte enregistré lors de la dernière exécution.
Les valeurs injectées par le déclencheur de cette exécution.
Ainsi, avec cette fonctionnalité, le générateur peut trier plusieurs opérations asynchrones. Le résultat de la première requête asynchrone sera transmis à la seconde en définissant la variable locale (resultValue dans l'exemple ci-dessus). La deuxième requête asynchrone ne peut être déclenchée que par la réponse de la première requête asynchrone. Ensuite, la deuxième requête asynchrone peut vérifier la valeur de la variable locale pour décider des étapes suivantes car la variable locale est une valeur injectée à partir de la réponse de la première requête.
Les difficultés des requêtes asynchrones sont:
enfer de rappel
perdre du contexte à moins de les passer comme paramètres dans le rappel.
le rendement et le générateur peuvent aider les deux.
Sans rendement et générateur, pour trier plusieurs requêtes asynchrones nécessite un rappel imbriqué avec des paramètres comme contexte qui n'est pas facile à lire et à maintenir.
Voici un exemple de requêtes asynchrones chaînées qui s'exécutent avec nodejs:
Ci-dessous le résultat en cours:
+++++++++++ start ++++++++++++
query1 0
+++++++++++ end ++++++++++++
query2 1
query4 0
Le modèle d'état ci-dessous peut faire la même chose pour l'exemple ci-dessus:
Voici le résultat en cours:
+++++++++++ start ++++++++++++
query1 0
+++++++++++ end ++++++++++++
query2 1
query4 0
la source
n'oubliez pas la syntaxe très utile «x du générateur» pour parcourir le générateur. Pas besoin du tout d'utiliser la fonction next ().
la source