7
votes

Settimeout sur la fonction asynchrone

J'ai une fonction asynchrone que je veux avoir un délai de 5 000 ms avant d'être tiré. J'essaie d'utiliser Settimeout () code> pour y parvenir. Cette fonction asynche se produit dans une boucle qui fonctionne plusieurs fois, la fonction ASYNC étant passée de différentes données à chaque fois, ainsi seinterval () code> ne peut pas être utilisé ici.

Problème: forte > La fonction ASYNC est déclenchée instantanément sans délai (impression de la console 5 effectué instantanément code> instantanément »et boucles sans retard. Qu'est-ce qui est arrivé, et comment puis-je le résoudre? P>

Code JavaScript FORT> P>

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


2 commentaires

Si "la liste" est vraiment un tableau, vous ne devriez pas itérer avec "pour ... dans". Utilisez plutôt un index numérique.


@Pointy oui c'est juste un tableau, oups :)


4 Réponses :


13
votes

Vous devez envelopper la fonction dans une autre fonction. Actuellement, vous appelez la fonction et transmettez la valeur de retour sous forme d'argument sur Settimeout . Le code ci-dessous transmettra (correctement) une fonction à Settimeout . Au bout de 5 secondes, la fonction s'exécute.

Je devais ajouter deux fonctions pour atteindre le comportement souhaité, en raison de problèmes de cadrage. Au bout de 5 secondes, la boucle est déjà terminée et la variable serait égale au dernier élément dans les annonces . xxx


8 commentaires

Cela déclenchera toujours n délais d'attente presque parallèles.


Merci pour la réponse! Il existe un délai initial de 5000 ms, mais les appels ultérieurs à l'asyncconftion se produisent instantanément! Les appels ultérieurs aux fonctions peuvent-ils retarder de sorte que chaque appel soit de 5 000 ms?


Il possède également le problème de la boucle / portée classique (la variable "listing")


J'ai remarqué que toutes les fonctions ASYNC obtiennent la même liste la variable comme signalée pointue


Réponse mise à jour pour ajouter un délai de 5 secondes entre chaque appel. @Poindy que le problème de la portée a déjà été adressé dans mon Ninja-edit lors de la première révision.


@jandy Maintenant, les fonctions sont déclenchées avec un délai de 5 secondes entre les deux.


@ROBW génial, a résolu plusieurs problèmes ici! Je ne comprends pas comment fonctionne la fonction de fermeture: fonction (listes) {...} (listes) Pourquoi existe-t-il un supplémentaire ajouté à la fin de la fonction? N'ont jamais vu cela avant ...


@Nyxynnyx Normalement, vous invoquez une fonction par func_name (paramètre) . Au lieu de définir une fonction nommée, vous pouvez également créer et invoquer une fonction anonyme: (fonction (argument) {...}) (paramètre) . En passant listing à la fonction anonyme, la variable à l'intérieur de la fonction anonyme ne changera pas lorsque la variable lister dans le corps de la boucle est mise à jour à nouveau .



-1
votes

C'est la différence.Le point clé est ce qui est asyncfunction faire? Pouvez-vous le coller? XXX


2 commentaires

Le premier "Settimeout ()" est incorrect, car il sera immédiatement invoquer "foo ()" et passez son résultat à "Settimeout ()". La seconde, passant une chaîne, est généralement considérée comme obsolète.


Oui, la chaîne de passage sera eval et ensuite l'exécuter sur la portée globale. Très mauvaise idée



1
votes

Ne sachant pas ce que votre asynccunction code> fait, il semblerait qu'il pouvait simplement renvoyer la fonction que vous avez transmise.

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

        //   then invoke the func
        func();
    }
}


2 commentaires

Merci, réduit une ligne de code en utilisant i au lieu de compteur . Asynccfunction utilise 2 valeurs de rappel dans DATA et les envoie à un autre serveur.


@Nyxynnyx: Pas tout à fait sûr de ce que vous voulez dire, mais vous pouvez passer tout ce dont vous avez besoin pour le func de rappel. Mon point principal était que vous avez déjà une fonction nommée, il n'est donc pas nécessaire d'ajouter deux niveaux de périmètre en ligne. Il vous suffit de modifier asyncfunction de sorte que retourne une fonction à appeler par le Settimeout . C'est une approche plus propre.



6
votes

Si vous utilisez ECMAScript6 Vous pouvez utiliser Promesse .

Créez donc une fonction de retard qui enveloppe l'appel au Settimeout en une promesse: P>

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


0 commentaires