J'ai le code JavaScript suivant:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable);
function2(someOtherVariable);
}
else {
doThis(someVariable);
}
});
Comment puis-je m'assurer qu'il function2
n'est appelé qu'après avoir function1
terminé?
javascript
jquery
Rrryyyaaannn
la source
la source
function1
exécution d' une opération asynchrone?Réponses:
Spécifiez un rappel anonyme et faites en sorte que function1 l'accepte:
$('a.button').click(function(){ if (condition == 'true'){ function1(someVariable, function() { function2(someOtherVariable); }); } else { doThis(someVariable); } }); function function1(param, callback) { ...do stuff callback(); }
la source
...do stuff
contient des éléments asynchrones? Function2 ne se déclenchera toujours pas comme prévu. L'exemple dans mon commentaire ci-dessus montre que parce que lafoo()
fonction contient du code asynchrone,bar()
ne déclenche pas son contenu une fois quefoo()
le contenu de son exécution est terminé, même en utilisant$.when().then()
pour les appeler l'un après l'autre. Cette réponse n'est valide que si (et seulement si) tous les éléments...do stuff
de votre code sont strictement synchrones.callBack()
après que tous les n appels asynchrones ont été effectués. Puisque OP n'a pas mentionné ce qu'il fait dans la fonction, il l'a supposé comme un appel asynchrone à un niveau.Si vous utilisez jQuery 1.5, vous pouvez utiliser le nouveau modèle Deferreds:
$('a.button').click(function(){ if(condition == 'true'){ $.when(function1()).then(function2()); } else { doThis(someVariable); } });
Edit: Lien de blog mis à jour:
Rebecca Murphy a fait un excellent article à ce sujet ici: http://rmurphey.com/blog/2010/12/25/deferreds-coming-to-jquery/
la source
$.when(function1).then(function2);
(sans les parenthèses qui appellent la fonction)?function1
devrait retourner une promesse. Dans ce cas, il doit s'agir de la fonction réellement exécutée et non de la référence. Quandresolve
est appelé sur cette promessefunction2
est alors exécuté. Cela s'explique facilement en supposant qu'ilfunction1
a un appel ajax. Ledone
rappel résoudrait alors la promesse. J'espère que c'est clair.Essaye ça :
function method1(){ // some code } function method2(){ // some code } $.ajax({ url:method1(), success:function(){ method2(); } })
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 .Les promesses sont une nouvelle (et bien meilleure) façon de gérer les opérations asynchrones en JavaScript:
$('a.button').click(function(){ if (condition == 'true'){ function1(someVariable).then(function() { //this function is executed after function1 function2(someOtherVariable); }); } else { doThis(someVariable); } }); function function1(param, callback) { return new Promise(function (fulfill, reject){ //do stuff fulfill(result); //if the action succeeded reject(error); //if the action did not succeed }); }
Cela peut sembler une surcharge importante pour cet exemple simple, mais pour un code plus complexe, c'est bien mieux que d'utiliser des rappels. Vous pouvez facilement chaîner plusieurs appels asynchrones à l'aide de plusieurs
then
instructions:function1(someVariable).then(function() { function2(someOtherVariable); }).then(function() { function3(); });
Vous pouvez également encapsuler facilement les reports jQuery (qui sont renvoyés par les
$.ajax
appels):Promise.resolve($.ajax(...params...)).then(function(result) { //whatever you want to do after the request });
Comme @charlietfl l'a noté, l'
jqXHR
objet renvoyé par$.ajax()
implémente l'Promise
interface. Il n'est donc pas nécessaire de l'envelopper dans unPromise
, il peut être utilisé directement:$.ajax(...params...).then(function(result) { //whatever you want to do after the request });
la source
Promise.resolve
le wrapping$.ajax
est anti-pattern puisque$.ajax
retourne la promessePromise
, il implémente simplement l'interface. Je ne sais pas comment il se comporte lors du passage d'un réelPromise
à sathen
méthode, ni ce quePromise.all
ferait a si ajqXHR
et a luiPromise
sont passés. Pour cela, je dois faire des tests supplémentaires. Mais merci pour l'indice, je l'ajouterai à la réponse!$.ajax.then
is not newOu vous pouvez déclencher un événement personnalisé lorsqu'une fonction se termine, puis le lier au document:
function a() { // first function code here $(document).trigger('function_a_complete'); } function b() { // second function code here } $(document).bind('function_a_complete', b);
En utilisant cette méthode, la fonction 'b' ne peut exécuter qu'APRÈS la fonction 'a', car le déclencheur n'existe que lorsque la fonction a est terminée.
la source
tu peux le faire comme ça
$.when(funtion1()).then(function(){ funtion2(); })
la source
Cela dépend de ce que fait function1.
Si function1 fait du javascript synchrone simple, comme la mise à jour d'une valeur div ou quelque chose, alors function2 se déclenchera après que function1 soit terminée.
Si function1 effectue un appel asynchrone, tel qu'un appel AJAX, vous devrez créer une méthode de "rappel" (la plupart des API ajax ont un paramètre de fonction de rappel). Appelez ensuite function2 dans le callback. par exemple:
function1() { new AjaxCall(ajaxOptions, MyCallback); } function MyCallback(result) { function2(result); }
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.
function method1(){ var dfd = new $.Deferred(); setTimeout(function(){ console.log("Inside Method - 1"); method2(dfd); }, 5000); return dfd.promise(); } function method2(dfd){ setTimeout(function(){ console.log("Inside Method - 2"); method3(dfd); }, 3000); } function method3(dfd){ setTimeout(function(){ console.log("Inside Method - 3"); dfd.resolve(); }, 3000); } function method4(){ console.log("Inside Method - 4"); } var call = method1(); $.when(call).then(function(cb){ method4(); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
la source
Si function1 est une fonction de synchronisation que vous souhaitez transformer en une fonction asynchrone, car elle prend du temps à se terminer et vous n'avez aucun contrôle dessus pour ajouter un rappel:
function function1 (someVariable) { var date = Date.now (); while (Date.now () - date < 2000); // function1 takes some time to complete console.log (someVariable); } function function2 (someVariable) { console.log (someVariable); } function onClick () { window.setTimeout (() => { function1 ("This is function1"); }, 0); window.setTimeout (() => { function2 ("This is function2"); }, 0); console.log ("Click handled"); // To show that the function will return before both functions are executed } onClick ();
La sortie sera:
... et après 2 secondes:
This is function 1 This is function 2
Cela fonctionne parce que l'appel de window.setTimeout () ajoutera une tâche à la boucle de tâches d'exécution JS, ce qui correspond à un appel asynchrone, et parce que le principe de base du "run-to-completion" du runtime JS garantit que onClick () n'est jamais interrompu avant la fin.
Notez que c'est aussi drôle que cela puisse être le code difficile à comprendre ...
la source