Si j'ai besoin d'appeler ces fonctions l'une après l'autre,
$('#art1').animate({'width':'1000px'},1000);
$('#art2').animate({'width':'1000px'},1000);
$('#art3').animate({'width':'1000px'},1000);
Je sais que dans jQuery je pourrais faire quelque chose comme:
$('#art1').animate({'width':'1000px'},1000,'linear',function(){
$('#art2').animate({'width':'1000px'},1000,'linear',function(){
$('#art3').animate({'width':'1000px'},1000);
});
});
Mais, supposons que je n'utilise pas jQuery et que je souhaite appeler:
some_3secs_function(some_value);
some_5secs_function(some_value);
some_8secs_function(some_value);
Comment dois-je appeler ces fonctions pour exécuter some_3secs_function
, et APRÈS cet appel se termine, puis exécuter some_5secs_function
et APRÈS cet appel se termine, puis appeler some_8secs_function
?
METTRE À JOUR:
Cela ne fonctionne toujours pas:
(function(callback){
$('#art1').animate({'width':'1000px'},1000);
callback();
})((function(callback2){
$('#art2').animate({'width':'1000px'},1000);
callback2();
})(function(){
$('#art3').animate({'width':'1000px'},1000);
}));
Trois animations démarrent en même temps
Où est mon erreur?
Réponses:
En Javascript, il existe des fonctions synchrones et asynchrones .
Fonctions synchrones
La plupart des fonctions en Javascript sont synchrones. Si vous appelez plusieurs fonctions synchrones d'affilée
ils exécuteront dans l'ordre.
doSomethingElse
ne démarrera pas tant qu'il ne sera pasdoSomething
terminé.doSomethingUsefulThisTime
, à son tour, ne démarrera pas tant qu'il ne sera pasdoSomethingElse
terminé.Fonctions asynchrones
La fonction asynchrone, cependant, n'attendra pas l'une l'autre. Regardons le même exemple de code que nous avions ci-dessus, en supposant cette fois que les fonctions sont asynchrones
Les fonctions seront initialisées dans l'ordre, mais elles s'exécuteront toutes à peu près en même temps. Vous ne pouvez pas toujours prédire lequel se terminera en premier: celui qui prendra le moins de temps à s'exécuter finira en premier.
Mais parfois, vous voulez que les fonctions asynchrones s'exécutent dans l'ordre, et parfois vous voulez que les fonctions synchrones s'exécutent de manière asynchrone. Heureusement, cela est possible avec les rappels et les délais d'attente, respectivement.
Rappels
Supposons que nous avons trois fonctions asynchrones que nous voulons exécuter dans l' ordre,
some_3secs_function
,some_5secs_function
etsome_8secs_function
.Étant donné que les fonctions peuvent être passées en tant qu'arguments en Javascript, vous pouvez transmettre une fonction en tant que rappel à exécuter une fois la fonction terminée.
Si nous créons les fonctions comme celle-ci
alors vous pouvez appeler alors dans l'ordre, comme ceci:
Timeouts
En Javascript, vous pouvez dire à une fonction de s'exécuter après un certain délai (en millisecondes). Cela peut, en effet, amener les fonctions synchrones à se comporter de manière asynchrone.
Si nous avons trois fonctions synchrones, nous pouvons les exécuter de manière asynchrone en utilisant la
setTimeout
fonction.Ceci est cependant un peu moche et viole le principe DRY [wikipedia] . Nous pourrions nettoyer un peu cela en créant une fonction qui accepte un tableau de fonctions et un délai d'expiration.
Cela peut être appelé ainsi:
En résumé, si vous avez des fonctions asynchrones que vous souhaitez exécuter de manière synchrone, utilisez des rappels, et si vous avez des fonctions synchrones que vous souhaitez exécuter de manière asynchrone, utilisez des délais d'expiration.
la source
Cette réponse utilise
promises
, une fonctionnalité JavaScript de laECMAScript 6
norme. Si votre plate-forme cible ne prend pas en chargepromises
, polyfill avec PromiseJs .Regardez ma réponse ici Attendez qu'une fonction avec animations soit terminée jusqu'à ce que vous exécutiez une autre fonction si vous souhaitez utiliser des
jQuery
animations.Voici à quoi ressemblerait votre code avec
ES6 Promises
etjQuery animations
.Les méthodes normales peuvent également être intégrées
Promises
.La
then
méthode est exécutée dès que lePromise
fichier est terminé. Normalement, la valeur de retour dufunction
passé àthen
est transmise au suivant en tant que résultat.Mais si a
Promise
est renvoyé, lathen
fonction suivante attend laPromise
fin de l'exécution et en reçoit les résultats (la valeur à laquelle elle est passéefulfill
).la source
Il semble que vous n'appréciez pas pleinement la différence entre l' exécution de fonctions synchrone et asynchrone .
Le code que vous avez fourni dans votre mise à jour exécute immédiatement chacune de vos fonctions de rappel, qui à leur tour démarrent immédiatement une animation. Les animations, cependant, s'exécutent de manière asyncronale . Cela fonctionne comme ceci:
setTimeout
avec une fonction contenant la prochaine étape d'animation et un délaisetTimeout
exécuteCela continue jusqu'à la fin de la dernière étape de l'animation. En attendant, vos fonctions synchrones sont terminées depuis longtemps. En d'autres termes, votre appel à la
animate
fonction ne prend pas vraiment 3 secondes. L'effet est simulé avec des retards et des rappels.Vous avez besoin d'une file d'attente . En interne, jQuery met les animations en file d'attente, n'exécutant votre rappel qu'une fois l'animation correspondante terminée. Si votre rappel démarre ensuite une autre animation, l'effet est qu'ils sont exécutés en séquence.
Dans le cas le plus simple, cela équivaut à ce qui suit:
Voici une fonction de bouclage asynchrone générale. Il appellera les fonctions données dans l'ordre, en attendant le nombre de secondes spécifié entre chacune.
Usage:
Vous pouvez évidemment modifier cela pour prendre des temps d'attente configurables ou pour exécuter immédiatement la première fonction ou pour arrêter l'exécution lorsqu'une fonction de la chaîne revient
false
ou auxapply
fonctions dans un contexte spécifié ou tout ce dont vous pourriez avoir besoin.la source
Je pense que la bibliothèque async vous fournira un moyen très élégant de le faire. Alors que les promesses et les rappels peuvent être un peu difficiles à jongler avec, async peut donner des modèles nets pour rationaliser votre processus de pensée. Pour exécuter des fonctions en série, vous devez les placer dans une cascade asynchrone . Dans le jargon asynchrone, chaque fonction est appelée a
task
qui prend quelques arguments et acallback
; qui est la fonction suivante de la séquence. La structure de base ressemblerait à quelque chose comme:J'ai juste essayé d'expliquer brièvement la structure ici. Lisez le guide de la cascade pour plus d'informations, il est plutôt bien écrit.
la source
vos fonctions devraient prendre une fonction de rappel, qui est appelée lorsqu'elle se termine.
alors l'utilisation serait comme:
la source
Je n'entrerai pas dans une discussion approfondie de setTimeout ici, mais:
la source
Puisque vous l'avez tagué avec javascript, j'irais avec un contrôle de minuterie puisque vos noms de fonction sont 3, 5 et 8 secondes. Alors démarrez votre chronomètre, 3 secondes après, appelez le premier, 5 secondes en appel le second, 8 secondes en appel le troisième, puis quand c'est fait, arrêtez le chronomètre.
Normalement, en Javascript, ce que vous avez est correct pour les fonctions qui s'exécutent les unes après les autres, mais comme il semble que vous essayez de faire une animation chronométrée, une minuterie serait votre meilleur pari.
la source
la source
next
?Vous pouvez également utiliser les promesses de cette manière:
Vous devrez rendre
some_value
global pour y accéder depuis l'intérieur du .thenAlternativement, à partir de la fonction externe, vous pouvez renvoyer la valeur que la fonction interne utiliserait, comme ceci:
la source
J'utilise une fonction 'waitUntil' basée sur setTimeout de javascript
Cela fonctionnerait parfaitement si vos fonctions définissaient une certaine condition sur true, que vous pourrez interroger. De plus, il est livré avec des délais d'expiration, ce qui vous offre des alternatives au cas où votre fonction échouerait à faire quelque chose (même dans la plage de temps. Pensez aux commentaires des utilisateurs!)
par exemple
la source
Si la méthode 1 doit être exécutée après la méthode 2, 3, 4. L'extrait de code suivant peut être la solution pour cela en utilisant l'objet Deferred en JavaScript.
la source