J'ai besoin d'une boucle qui attend un appel asynchrone avant de continuer. Quelque chose comme:
for ( /* ... */ ) {
someFunction(param1, praram2, function(result) {
// Okay, for cycle could continue
})
}
alert("For cycle ended");
Comment pourrais-je faire ça? As tu des idées?
javascript
Marry Hoffser
la source
la source
( /* ... */ )
ressemble à un monstre et j'ai peur maintenant :(Réponses:
Vous ne pouvez pas mélanger synchrone et asynchrone en JavaScript si vous bloquez le script, vous bloquez le navigateur.
Vous devez suivre le chemin complet de l'événement ici, heureusement, nous pouvons cacher les trucs laids.
EDIT: mise à jour du code.
Cela nous fournira une fonction asynchrone
loop
, vous pourrez bien sûr la modifier encore plus pour prendre par exemple une fonction pour vérifier la condition de la boucle etc.Passons maintenant au test:
Et la sortie:
la source
loop.break()
faire? Juste un moyen de forcer si tu veux?J'ai simplifié ceci:
FONCTION:
USAGE:
EXEMPLE: http://jsfiddle.net/NXTv7/8/
la source
Une alternative plus propre à ce que @Ivo a suggéré serait une file d'attente de méthodes asynchrones , en supposant que vous ne devez effectuer qu'un seul appel asynchrone pour la collection.
(Voir cet article de Dustin Diaz pour une explication plus détaillée)
Vous créez simplement une nouvelle instance de
Queue
, ajoutez les rappels dont vous avez besoin, puis videz la file d'attente avec la réponse asynchrone.Un avantage supplémentaire de ce modèle est que vous pouvez ajouter plusieurs fonctions à la file d'attente au lieu d'une seule.
Si vous avez un objet qui contient des fonctions d'itérateur, vous pouvez ajouter la prise en charge de cette file d'attente en arrière-plan et écrire du code qui semble synchrone, mais qui ne l'est pas:
écrivez simplement
each
pour mettre la fonction anonyme dans la file d'attente au lieu de l'exécuter immédiatement, puis videz la file d'attente lorsque votre appel asynchrone est terminé. Il s'agit d'un modèle de conception très simple et puissant.PS Si vous utilisez jQuery, vous disposez déjà d'une file d'attente de méthode asynchrone appelée jQuery.Deferred .
la source
someFunction
vous avez bien compris la question cela ne donnera pas le comportement souhaité, il semble qu'elle veuille faire des rappels dans lesquels retarder le reste de la boucle, votre modèle met en place une liste de fonctions qui seront exécutées dans l'ordre et recevront toutes les résultats d' un autre appel de fonction. C'est un bon schéma mais je ne pense pas qu'il corresponde à la question en question.setTimeout
. Vous risquez un comportement involontaire si le code est exécuté plus rapidement que prévu.setTimeout
si le rappel ne prend que la moitié du temps, eh bien le code s'exécute à nouveau plus rapidement ... alors à quoi ça sert ? Le "code" dans la "boucle" est toujours en ordre, si vous faites des choses en dehors de celui-ci avant le rappel complet, vous appelez déjà pour un problème, mais là encore c'est un thread unique, j'ai du mal à trouver un scénario oùsetTimeout
casserait quelque chose, sans autre mauvaise conception.Regardez aussi cette splendide bibliothèque caolan / async . Votre
for
boucle peut facilement être réalisée en utilisant mapSeries ou series .Je pourrais publier un exemple de code si votre exemple contenait plus de détails.
la source
Nous pouvons également utiliser l'aide de jquery.Deferred. dans ce cas, la fonction asyncLoop ressemblerait à ceci:
la fonction de rappel ressemblera à ceci:
exemple de fonction qui résout différé:
la source
J'utilise le "setTimeout (Func, 0);" truc pendant environ un an. Voici quelques recherches récentes que j'ai rédigées pour expliquer comment l'accélérer un peu. Si vous voulez juste la réponse, passez à l'étape 4. Les étapes 1 2 et 3 expliquent le raisonnement et la mécanique;
la source
Étant donné une fonction de travail asynchrone
someFunction
qui rappellera une fonction de résultat avec unresult
argument indiquant si la boucle doit continuer ou non:Afin de vérifier s'il faut ou non terminer la boucle, la fonction de travail
someFunction
peut transmettre la fonction de résultat à d'autres opérations asynchrones. En outre, l'expression entière peut être encapsulée dans une fonction asynchrone en prenant une fonctiondone
comme rappel.la source
Si vous aimez la réponse de wilsonpage mais que vous êtes plus habitué à utiliser la syntaxe de async.js, voici une variante:
La démo peut être trouvée ici - http://jsfiddle.net/NXTv7/8/
la source
Voici un autre exemple qui, à mon avis, est plus lisible que d'autres, où vous enveloppez votre fonction asynchrone dans une fonction qui prend une
done
fonction, l'index de la boucle actuelle et le résultat (le cas échéant) de l'appel async précédent:Une fois
done()
invoqué, il déclenche le prochain appel asynchrone, en passant à nouveau la fonction done, l'index actuel et le résultat précédent. Une fois la boucle entière terminée, la boucle fourniecallback
sera appelée.Voici un extrait que vous pouvez exécuter:
la source
Vous pouvez utiliser
async await
introduit dans ES7:Cela ne fonctionne que si
someFunction
retournez une promesse!Si
someFunction
ne retournez pas une promesse, vous pouvez lui faire renvoyer une promesse par vous-même comme ceci:Puis remplacez cette ligne
await someFunction(param1, param2);
parawait asynSomeFunction(param1, param2);
Veuillez comprendre les promesses avant d'écrire du
async await
code!la source
Unexpected await inside loop
.javascript
problème. Cet avertissement provient de votreeslint
configuration. Je désactive toujours cette règleeslint
parce que dans la plupart des endroits où j'ai vraiment besoin d'attendre dans la bouclehttp://cuzztuts.blogspot.ro/2011/12/js-async-for-very-cool.html
ÉDITER:
lien depuis github: https://github.com/cuzzea/lib_repo/blob/master/cuzzea/js/functions/core/async_for.js
Cette fonction vous permet de créer un pourcentage de rupture dans la boucle for en utilisant settings.limit. La propriété limit est juste un entier, mais lorsqu'elle est définie comme array.length * 0.1, cela rendra le settings.limit_callback appelé tous les 10%.
exemple:
la source
Une solution basée sur une bibliothèque de promesses:
la source
J'avais besoin d'appeler des
X
heures de fonction asynchrones , chaque itération devait avoir lieu après la précédente, alors j'ai écrit un petite bibliothèque qui peut être utilisée comme ceci:Chaque fois qu'une fonction de boucle définie par l'utilisateur est appelée, elle a deux arguments, un index d'itération et une valeur de retour de l'appel précédent.
Voici un exemple de sortie:
la source