L'appel d'une fonction asynchrone à l'intérieur d'une boucle en JavaScript
J'ai le code suivant:
for(var i = 0; i < list.length; i++){
mc_cli.get(list[i], function(err, response) {
do_something(i);
});
}
mc_cli
est une connexion à une base de données de memcache. Comme vous pouvez l'imaginer, la fonction de rappel est asynchrone, donc c'est peut être exécutée lorsque la boucle for est déjà terminée. Aussi, lors de l'appel de cette façon do_something(i)
il utilise toujours la dernière valeur de la boucle for.
J'ai essayé avec une fermeture de cette façon
do_something((function(x){return x})(i))
mais apparemment c'est encore une fois en utilisant toujours la dernière valeur de l'indice de la boucle for.
J'ai aussi essayé de la déclaration d'une fonction avant la boucle for comme ceci:
var create_closure = function(i) {
return function() {
return i;
}
}
et puis l'appel de
do_something(create_closure(i)())
mais encore une fois sans succès, avec la valeur de retour d'être toujours la dernière valeur de la boucle for.
Quelqu'un peut-il me dire ce que je fais mal avec les bouchons? J'ai cru comprendre, mais je ne peux pas comprendre pourquoi cela ne fonctionne pas.
Vous devez vous connecter pour publier un commentaire.
Puisque vous êtes en cours d'exécution à travers un tableau, vous pouvez simplement utiliser
forEach
qui fournit l'élément de la liste, et l'indice dans la fonction de rappel. Itération aura son propre champ d'application.C'est de l'asynchrone fonction à l'intérieur d'une boucle de paradigme, et j'ai l'habitude de traiter avec elle en utilisant un immédiatement appelé-anonyme-fonction. Cela garantit que les fonctions asynchrones appelée avec la valeur correcte de la variable d'index.
D'accord, parfait. De sorte que toutes les fonctions asynchrones ont été mis en place, et la boucle s'arrête. Maintenant, il est impossible de dire quand ces fonctions complètes, en raison de leur nature asynchrone, ou dans quel ordre ils vont complète. Si vous disposez d'un code qui doit attendre jusqu'à ce que toutes ces fonctions soient terminées avant l'exécution, je conseille de garder un simple comptage du nombre de fonctions ont fini:
Je sais que c'est un vieux thread mais de toute façon, l'ajout de ma réponse. ES2015
let
a la particularité de reliaison la variable de boucle à chaque itération, de sorte qu'il maintient la valeur de la variable de boucle dans des rappels asynchrones, de sorte que vous pouvez essayer de le ci-dessous un:Mais de toute façon, il est préférable d'utiliser
forEach
ou créer une fermeture à l'aide immédiatement appelée fonction, depuislet
est ES2015 fonctionnalité et pourrait ne pas être en charge tous les navigateurs et les implémentations. De ici sousBindings ->let->for/for-in loop iteration scope
je peux voir, il n'est pas pris en charge jusqu'à Edge 13 et même jusqu'à Firefox 49 (je n'ai pas vérifié dans ces navigateurs). Il dit même qu'il n'est pas pris en charge avec le Nœud 4, mais j'ai personnellement testé et il semble qu'il est pris en charge.for loop
ne fonctionne pas comme il le suppose. J'ai été en utilisantvar i = 0
toute cette période, jusqu'à ce que je vois votre post. - Je changervar i = 0
àlet i = 0
et de magie, tout fonctionne très bien. Comment puis-je vous donne à tous ma réputation, vous méritez tous ça...let
a été le gagnant pour moiVous étiez assez proches, mais vous devez passer à la fermeture de
get
au lieu de le mettre à l'intérieur de la fonction de rappel:Essayer ce, à l'aide de la
async/await
syntaxe etPromise
Cela va arrêter la boucle à chaque cycle jusqu'à ce que le
next()
fonction est déclenchéeES2017: Vous pouvez envelopper les async code à l'intérieur d'une fonction(dire XHRPost) de retour d'une promesse( Async code à l'intérieur de la promesse).
Puis appeler la fonction(XHRPost) à l'intérieur de la boucle for, mais avec la magie de mot clé Await. 🙂
Si vous souhaitez exécuter asynchrone fonctions à l'intérieur d'une boucle, mais souhaitez tout de même conserver l'index ou d'autres variables après un rappel est exécuté, vous pouvez insérer votre code dans une IIFE (immédiatement invoquées par l'expression de fonction).
À l'aide de ES6 (texte dactylographié), vous pouvez utiliser les avantages de
async
etawait
:async/await
fait partie de la langue!