Ожидание завершения всех запросов nodeJS и добавление к ним небольшой задержки - PullRequest
0 голосов
/ 21 мая 2018

У меня есть приложение, которое предназначено для взаимодействия с удаленным API.Я должен сделать около 10000 (10k) запросов, не слишком быстро, чтобы защита от ddos ​​заблокировала меня.Значит мне нужно добавить небольшую задержку.

Код

 var promises = [];
 for(var i = 0 ; i < list.length;i++)
 {
  console.log("checking " + list[i]);
  promises.push(doRequest(token,Username));
 }

 Promise.all(promises).then(function()
 {
  console.log("done");
 },function(err){
  console.log("oops");
 });

doRequest выглядит так:

function doRequest(token,username)
{
  var checkUsername = { method: 'GET',
  url: link + username,
  headers: 
   { AUTHORIZATION: 'Bearer ' + token,
     Accept: 'application/json' } };
    return new Promise(function (resolve, reject) 
    {
      request(checkUsername , function (error, res, body) {
        try
        {
          var json = JSON.parse(body);
          if(json.success)
          {
            resolve(username);
          }
          else
          {
            reject(username);
          }
        }
        catch(exception)
        {
          console.log(body);
          reject(exception);
        }
      });
    });
}

Кажется, что каждый раз, когда я попадаю в JSON.parse (body), происходит сбой, потому что я отправляю запрос слишком быстро, чтобы удаленный сервер не считал меня спам-ботом, в результате чего мое тело просто не определеноили просто код выполняется слишком быстро, что приводит к тому же самому.

Как я могу исправить эту ситуацию, сохраняя при этом асинхронную природу моего кода, поэтому он все еще относительно быстр?

Ответы [ 3 ]

0 голосов
/ 21 мая 2018

Если вы используете версию Node, достаточно свежую для async/await, это довольно безболезненно.Вы можете разбить свои запросы на группы, дождаться каждой группы, приостановить (ожидая тайм-аут) и продолжить.Например:

function getGroups(start, end, list) {
  var promises = [];
  end = end > list.length ? list.length : end
  for (var i = start; i < end; i++) {
    console.log("checking " + list[i]);
    promises.push(doRequest(i));
  }
  return Promise.all(promises)
}

function doRequest(i) {
  // fake request
  return new Promise(resolve => setTimeout(() => resolve(i), 750))
}


async function get(list) {
  const group_size = 5
  const wait_time = 1500
  for (var i = 0; i < list.length; i += group_size) {
    console.log("getting group")
    let group_result = await (getGroups(i, i + group_size, list))
    console.log("results of group: ", group_result)
    console.log("Waiting")
    await new Promise(resolve => setTimeout(resolve, wait_time))

  }
}
let urls = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
get(urls)

Если вы просто хотите поместить небольшую задержку между каждым запросом, вы можете использовать async/await в цикле с чем-то вроде:

function doRequest(i) {
  /* fake request */
  console.log("requesting: ", i)
  return new Promise(resolve => setTimeout(() => resolve(i), 250))
}

let urls = [0, 1, 2, 3, 4, 5]

async function get() {
  let results = []
  for (url of urls) {
    results.push(await doRequest(url))
    await new Promise(resolve => setTimeout(resolve, 200))
  }
  return results
}
get().then(r => console.log("results: ", r))

Конечно, вы захотите выполнить проверку ошибок и т. Д. ...

0 голосов
/ 21 мая 2018

У NPM есть пара пакетов для обещаний регулирования.Это топ:

https://www.npmjs.com/package/promise-throttle

0 голосов
/ 21 мая 2018

Ответ зависит от того, как быстро вы хотите попробовать и сделать это.Сколько запросов вам разрешено делать одновременно и т. Д. Вот возможная стратегия.Вы можете подумать об этом, выяснить, сколько параллельных запросов вам разрешено делать, и разбить работу на синхронные блоки, которые все выполняются одновременно.

// the number of simultaneous requests that wont cause problems
const allowedSimultaneous = 10

// create each chain
const chains = Array(allowedSimultaneous).fill(Promise.resolve())

// now build a synchronous list for each block
list.forEach((item, i) => {
  const chainIndex = i % allowedSimultaneous
  chains[chainIndex] = chains[chainIndex]
    .then(() => doRequest(token, Username))
})

// finally use .all() to catch when all chains are completed
Promise.all(chains).then(() => console.log('done'))

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

. Никаких задержек вообще не нужно, поскольку будут выполняться только allowedSimultaneous вызовы, но если вам нужна какая-то задержка,Вы можете просто отложить после каждого doRequest

...