8
votes

Comment ralentir cette requête HTTP en boucle de nœud?

J'essaie d'appeler cette API avec le Demande module environ 200-300 fois avec une fonction lambda. J'ai besoin d'ajouter une seconde entre chaque appel afin que je ne reçois pas une réponse 429. J'ai essayé de quelques façons différentes de faire cela, mais il semble ignorer le code de le ralentir.

Comment les gens ralentissent-ils normalement ces demandes dans AWS Lambda? Ce serait génial si je pouvais insérer quelque chose comme les utilitaires.sleep (1000) dans la boucle pour que cela soit attendu une seconde avant de continuer. Je suis sûr qu'il y a une solution simple à ce sujet, mais tous les exemples que j'ai vus semblent le rendre complexe. xxx


4 commentaires

Exécution de la fonction récursive avec Settimeout () entre les appels


Je vous donne un exemple. Au temps t0 vous itérer 1000 fois et démarrez 1000 Settimeout avec 1000 ms de délai. Je ne sais pas à quel point le temps passe entre la première fourmi l'appel 1000 mais très très peu. Ensuite, vous commencez à 1000 fois votre méthode après exactement 1s. Vous devriez incrémenter votre temps à chaque fois. ES: settimeout (fonction, 1000 + i)


Peut-être que ceci est utile caolan.github.io/async/docs.html#.achelimit < / a>


Ne fais pas ça: thedailywtf.com/articles/Le-Speedup-loop


4 Réponses :


1
votes

Vous pouvez faire quelque chose comme ceci: xxx

y est le délai maximum (1000 + y) alors vous voulez ( ES 5 sec) et x est la minuterie pour chaque appel (ES x = 10 : 1000 1010 10020,1030, ...

Si vous voulez 1s chaque appel: xxx

modifier xxx


8 commentaires

Cette solution créera des délits plus longs et plus longs, mais cela ne tient pas compte du temps que chaque appel de l'API prendra. Si l'API spécifie une heure de 1000 ms entre les appels, nous faisons notre premier appel et cela revient finalement, et 1000ms plus tard, nous effectuons un autre appel, la variabilité dans le temps que les appels prennent peut signifier que nous cassions les exigences de synchronisation de l'API et que vous soyez sur la liste noire.


@broGuinn oui je sais. Mais si vous attendez une seconde après la réponse (votre réponse), vous attendez beaucoup ( ttl et obtenir les données). Sinon, vous pouvez simplement faire la prochaine demande de manière récursive dans le rappel.


Oui, pensais aussi. Idéalement, nous avons une sorte d'util qui prend une fonction de retour de promesse et un délai d'attente et retourne une promesse après que la fonction a terminé et le délai d'attente est effectué. Peut-être comme promess.all ([promess.wait (1000), promesse.resolve (Makequest ())])


@gianlucatursi J'ai ajouté le code ci-dessus à ma boucle pour la boucle, mais il semble toujours que cela puisse les appeler aller plus vite qu'une seconde entre les appels. J'ai même changé le 1000 à 4000 Settimeout (Calltoggl (éléments [i]), 1000 + (i * 4000)); avec le même résultat. @BroGuinn Vous avez raison dans votre commentaire, mais pour cette API, je n'ai pas besoin de vous inquiéter de la fréquence à laquelle j'appelle l'API. Il ne peut tout simplement pas être appelé trop souvent. (Leurs documents disent environ 1 demande par seconde est recommandé.)


@Britgwaltney avec ce code La fonction n'exécutera pas chaque seconde? étrange. Pouvez-vous mettre un console.log (nouvelle date ()) en tant que première ligne de calltoggl ? Vous devriez voir chaque seconde une nouvelle date


Voici ce que la sortie des journaux Dropbox .COM / S / UWOH4NCKHHQU7NN4 / ... Pensez-vous que cela pourrait se rapporter à ce fil? Stackoverflow.com/questions/9184702/... < / a>


@Britgwaltney je ne sais pas mais vous pouvez essayer avec Settimeout (CallToggl, (i * 1000), éléments [i]); ou SETTITimeOUT (Fonction (Articles [i ]);}, 2000); . Si cela fonctionne, j'ai réalisé quelque chose de nouveau: D


Vous ne pouvez pas faire cela de cette façon. Settimeout signifie que même ne sera viré pas moins que x millisecondes. En d'autres termes, si vous définissez 1000, 2000, 3000. Si la manipulation de la première demande prend 2 secondes et que la dernière demande prend 10 ms pour être manipulée. La troisième demande sera tirée de 10 ms après la deuxième demande qui enfreindra la règle. Le seul moyen d'assurer que vous ne brisez pas la règle consiste à des appels en chaîne.




0
votes

Comme vous le savez probablement, le code JavaScript ne bloque pas sur IO (sauf si l'utilisation de l'API de synchronisation spécifique qui bloque votre code entier qui est une mauvaise pratique qui doit être évitée à moins que vous ayez une très bonne raison de bloquer le code complet (chargement de la configuration Les fichiers sur le démarrage ... etc ...))

Donc, de sorte que vous devez faire, c'est simplement attendre la réponse

Il était un peu compliqué dans le passé pour tout orchestrer tout, Mais actuellement, en utilisant --Harmony Drapeau (pour activer les dernières fonctionnalités JS dans le nœud), vous pouvez utiliser la nouvelle syntaxe de fonctions ASYNC brillante. (Await / ASYNC)

La fonction que vous utilisez à l'intérieur doit être déclarée ASYNC, puis après chaque itération, vous devez attendre la réponse de cet appel HTTP à l'aide de "attendre" mot clé. Ce mot clé donne le code comme si son blocage et attendre la réponse résolue, bien que ce n'est pas.

J'ai utilisé "Fetch" au lieu de "Demande" car il joue bien avec des fonctions ASYNC (en promesse) Mais vous pouvez utiliser une autre méthode aussi longtemps que vous retournez une promesse. (Vous pouvez même vous en rendre compte de votre API basée sur la rappel existant avec un objet prometteur, mais cela fera tout ce qui est l'air plus laborieux, alors s'il vous plaît ne faites pas :))

Voici le code modifié. Je ne suis pas vraiment sûr que cela fonctionne comme ça. Mais l'idée est assez claire, je pense.

Sur n'importe quel cas, c'est une excellente occasion pour vous d'apprendre à travailler avec Async Fonctions au cas où vous ne les utiliseriez pas déjà, ils rendent vraiment la vie plus facile. xxx


0 commentaires

1
votes

Vous pouvez chaîner les demandes ensemble:

function findProjects(items){

    var toggleData = [];

    // chain requests with delay
    items.reduce(function (requestChain, item) {
      return requestChain
        .then(callToggle.bind(null, item))
        .then(wait.bind(null, 1000));
    }, Promise.resolve());

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

    function callToggle(data) {
        request({
            'url': 'https://www.toggl.com/api/v8/projects/' + data.toggle.data.id,
            'method': 'GET',
            'headers': {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            },
            'auth': {
                'user': 'xxxxxxx',
                'pass': 'api_token'
        }}, function( error, response, body ){
            if( error ) {

                console.log( error );
                context.done( null, error );
            } else {

                console.log(response.statusCode, "toggle projects were listed");
                var info = JSON.parse(body);
                toggleData.push(info);
            }
        });
    }

    findDocument( toggleData );   
}


1 commentaires

J'ai eu une question similaire et je veux que vous sachiez que cette réponse était la perfection. Merci!