Comme le titre l'indique. Comment puis-je faire cela?
Je veux appeler whenAllDone()
après que la boucle forEach ait traversé chaque élément et effectué un traitement asynchrone.
[1, 2, 3].forEach(
function(item, index, array, done) {
asyncFunction(item, function itemDone() {
console.log(item + " done");
done();
});
}, function allDone() {
console.log("All done");
whenAllDone();
}
);
Possible de le faire fonctionner comme ça? Lorsque le deuxième argument de forEach est une fonction de rappel qui s'exécute une fois qu'il a parcouru toutes les itérations?
Production attendue:
3 done
1 done
2 done
All done!
javascript
node.js
asynchronous
callback
Dan Andreasson
la source
la source
forEach
méthode de tableau standard avait undone
paramètre deallDone
rappel et un rappel!Réponses:
Array.forEach
ne fournit pas cette finesse (oh si c'est le cas) mais il existe plusieurs façons d'accomplir ce que vous voulez:Utiliser un simple compteur
(merci à @vanuan et à d'autres) Cette approche garantit que tous les éléments sont traités avant d'appeler le rappel "terminé". Vous devez utiliser un compteur qui est mis à jour dans le rappel. Selon la valeur du paramètre d'index ne fournit pas la même garantie, car l'ordre de retour des opérations asynchrones n'est pas garanti.
Utilisation des promesses ES6
(une bibliothèque de promesses peut être utilisée pour les anciens navigateurs):
Traiter toutes les demandes garantissant une exécution synchrone (par exemple 1 puis 2 puis 3)
Traiter toutes les demandes asynchrones sans exécution "synchrone" (2 peuvent se terminer plus rapidement que 1)
Utilisation d'une bibliothèque asynchrone
Il existe d'autres bibliothèques asynchrones, async étant la plus populaire, qui fournissent des mécanismes pour exprimer ce que vous voulez.
ÉditerLe corps de la question a été modifié pour supprimer l'exemple de code précédemment synchrone, j'ai donc mis à jour ma réponse pour clarifier. L'exemple d'origine utilisait du code synchrone pour modéliser le comportement asynchrone, donc les éléments suivants s'appliquaient:
array.forEach
est synchrone et estres.write
donc, vous pouvez donc simplement mettre votre rappel après votre appel à foreach:la source
if(index === array.length - 1)
et retireritemsProcessed
Si vous rencontrez des fonctions asynchrones et que vous voulez vous assurer qu'avant d'exécuter le code, il termine sa tâche, nous pouvons toujours utiliser la fonction de rappel.
Par exemple:
Remarque:
functionAfterForEach
est la fonction à exécuter une fois les tâches foreach terminées.asynchronous
est la fonction asynchrone exécutée à l'intérieur de foreach.la source
J'espère que cela résoudra votre problème, je travaille généralement avec cela lorsque j'ai besoin d'exécuter forEach avec des tâches asynchrones à l'intérieur.
avec
la source
C'est étrange combien de réponses incorrectes ont été données au cas asynchrone ! On peut simplement montrer que la vérification de l'index ne fournit pas le comportement attendu:
production:
Si nous vérifions
index === array.length - 1
, le rappel sera appelé à la fin de la première itération, tandis que le premier élément est toujours en attente!Pour résoudre ce problème sans utiliser de bibliothèques externes telles que async, je pense que votre meilleur pari est d'enregistrer la longueur de la liste et de la décrémenter si après chaque itération. Puisqu'il n'y a qu'un fil, nous sommes sûrs qu'il n'y a aucune chance de condition de course.
la source
Avec ES2018, vous pouvez utiliser des itérateurs asynchrones:
la source
Ma solution sans promesse (cela garantit que chaque action est terminée avant que la prochaine ne commence):
la source
la source
C'est la solution pour Node.js qui est asynchrone.
en utilisant le package async npm.
(JavaScript) Synchronisation de forEach Loop avec les rappels à l'intérieur
la source
Ma solution:
Exemple:
la source
J'essaye Easy Way pour le résoudre, je le partage avec vous:
request
est la fonction de la bibliothèque mssql dans Node js. Cela peut remplacer chaque fonction ou code que vous souhaitez. Bonne chancela source
la source
Vous ne devriez pas avoir besoin d'un rappel pour parcourir une liste. Ajoutez simplement l'
end()
appel après la boucle.la source
res.write
n'est PAS une opération asynchrone, donc votre code ne fonctionnera pas.Une solution simple serait comme suivre
la source
Que diriez-vous de setInterval, pour vérifier le nombre d'itérations complet, apporte une garantie. Je ne sais pas si cela ne surchargera pas la portée, mais je l'utilise et semble être celui
la source