Как сделать синхронную задержку внутри цикла? - PullRequest
0 голосов
/ 15 июня 2019

Я пишу скрипт NodeJS, который вызывает группу API через GET (используя request из npm) и сохраняет ответы в файле JSON.Я использую for для циклического перебора идентификаторов для передачи в API, но у меня возникают проблемы с задержкой между пакетами вызовов, поэтому я не спамлю сервер API и не злюсь на меня (ограничение скорости),Кто-нибудь знает, как это сделать?

Мой текущий код (без каких-либо задержек):

var fs       = require('fs');
var request  = require('request');

// run through the IDs
for(var i = 1; i <= 4; i++)
{
    (function(i)
    {
        callAPIs(i); // call our APIs
    })(i);
}

function callAPIs(id)
{
    // call some APIs and store the responses asynchronously, for example:
    request.get("https://example.com/api/?id=" + id, (err, response, body) =>
        {
            if (err)
                {throw err;}

            fs.writeFile("./result/" + id + '/' + id + '_example.json', body, function (err)
            {
                if (err)
                    {throw err;}
            });
        });
}

Я ищу это поведение:

callAPIs(1); // start a burst of calls for ID# 1

// wait a bit...

callAPIs(2); // start a burst of calls for ID# 2

// wait a bit...

// etc

Ответы [ 3 ]

3 голосов
/ 15 июня 2019

Вы можете использовать новые ES6 async/await

(async () => {
    for(var i = 1; i <= 4; i++)
    {
        console.log(`Calling API(${i})`)
        await callAPIs(i);
        console.log(`Done API(${i})`)
    }
})();

function callAPIs(id)
{
    return new Promise(resolve => {
        // Simulating your network request delay
        setTimeout(() => {
            // Do your network success handler function or other stuff
            return resolve(1)
        }, 2 * 1000)
    });
}

Рабочая демоверсия: https://runkit.com/5d054715c94464001a79259a/5d0547154028940013de9e3c

3 голосов
/ 15 июня 2019

В nodeJS вы не делаете пауз, вы используете его асинхронный характер, чтобы дождаться результата предыдущих задач, прежде чем продолжить выполнение следующей задачи.

function callAPIs(id) {
  return new Promise((resolve, reject) => {
  // call some APIs and store the responses asynchronously, for example:
    request.get("https://example.com/api/?id=" + id, (err, response, body) => {
      if (err) {
        reject(err);
      }

      fs.writeFile(`./result/${id}/${id}_example.json`, body, err => {
        if (err) {
          reject(err);
        }

        resolve();
      });
    });
  });
}

for (let i = 1; i <= 4; i++) {
  await callAPIs(array[index], index, array);
}

Этот код выполнит запрос, запишет файли, как только он будет записан на диск, он обработает следующий файл.

Ожидание фиксированного времени перед обработкой следующей задачи, что, если это займет немного больше времени?Что делать, если вы тратите 3 секунды, чтобы убедиться, что это было сделано ...?

0 голосов
/ 15 июня 2019

Возможно, вы также захотите взглянуть на асинхронный модуль.Он состоит из метода async.times, который поможет вам достичь нужных результатов.

var fs = require('fs');
var request = require('request');
var async = require('async');


// run through the IDs
async.times(4, (id, next) => {
    // call some APIs and store the responses asynchronously, for example:
    request.get("https://example.com/api/?id=" + id, (err, response, body) => {
        if (err) {
            next(err, null);
        } else {
            fs.writeFile("./result/" + id + '/' + id + '_example.json', body, function (err) {
                if (err) {
                    next(err, null);
                } else
                    next(null, null);
            });
        }
    });
}, (err) => {
    if (err)
        throw err
});

Вы можете прочитать об этом по следующему общему URL: https://caolan.github.io/async/v3/docs.html#times

...