SetTimeout sur la fonction asynchrone

J'ai une fonction asynchrone que je veux avoir un délai de 5000 ms avant d'être licencié. J'essaie d'utiliser setTimeout() pour y parvenir. Cette fonction asynchrone se produit dans une boucle qui s'exécute à plusieurs reprises, la fonction asynchmène étant passée différentes données à chaque fois, donc setInterval() ne peut pas être utilisé ici.

Problème: la fonction asynchique se déclenche instantanément sans délai (la console imprime 5 Done messages instantanément et les boucles sans délai. Qu'est-il arrivé et comment puis-je le résoudre?

Code Javascript

 someFunction(listings, function() { for (var i in listings ) { var listing = listings[i]; setTimeout(asyncFunction(listing, function(data) { console.log('Done'); }), 5000); } }); 

Vous devez envelopper la fonction dans une autre fonction. Actuellement, vous invoquez la fonction et passez la valeur de retour en tant qu'argument pour setTimeout . Le code ci-dessous passera (correctement) une fonction à setTimeout . Après 5 secondes, la fonction s'effectue.

J'ai dû ajouter deux fonctions pour atteindre le comportement souhaité, en raison de problèmes de portée. Après 5 secondes, la boucle a déjà terminé, et la variable d' listing serait égale au dernier élément dans les listings .

 someFunction(listings, function() { var counter = 0; // Define counter for 5 second-delays between each call for (var i in listings ) { var listing = listings[i]; (function(listing){ //Closure function setTimeout(function(){ //setTimeout function // Because of the closure, `listing` is unique asyncFunction(listing, function(a, b) { console.log('Done'); }); }, 5000 * ++counter); //Increase counter for each loop })(listing); } }); 

Si vous utilisez ECMAScript6, vous pouvez utiliser Promise .

Créez donc une fonction de retard qui enveloppe l'appel au setTimeout dans une promesse:

 function delay(ms) { return new Promise(function (resolve) { return setTimeout(resolve, ms); }); }; 

Et vous pouvez l'utiliser comme ça:

 someFunction(listings, function() { for (var i in listings ) { var listing = listings[i]; delay(5000).then(() => { return asyncFunction(listing); }).then(() => { console.log('Done'); }); } }); 

Si vous utilisez ECMAScript 2017, vous pouvez utiliser aync / await .

Les fonctions asynchrones deviennent prometteuses, de sorte que vous ne devez pas modifier le code de la fonction de retard.

 async someFunction(listings, function() { for (var i in listings ) { var listing = listings[i]; await delay(5000); await asyncFunction(listing); console.log('Done'); } }); 

Sans savoir ce que fait votre asyncFunction , il semblerait qu'il pourrait simplement renvoyer la fonction que vous avez transmise.

 someFunction(listings, function() { for (var i = 0; i < listings.length; ++i ) { setTimeout(asyncFunction(listings[i], function(data) { console.log('Done'); }), 5000 * i); } }); function asyncFunction( lstng, func ) { return func; } 

Bien que je m'attends à ce que vous deviez compléter une logique supplémentaire.

 function asyncFunction( lstng, func ) { return function() { // do some stuff with the listing // then invoke the func func(); } } 

Maintenant, votre asyncFunction enveloppe tout ce qui est nécessaire dans une nouvelle fonction renvoyée à setTimeout . La nouvelle fonction appelle également le rappel que vous avez passé.


JSFIDDLE DEMO

C'est la différence. Le point clé est ce que fait l' asyncFunction ? Pouvez-vous le coller?

 var foo=function(){ alert("BAR"); return function(){ alert("I AM!"); }; } setTimeout(foo(),4000); setTimeout(foo,5000);