JavaScript / Promise - определение времени ожидания между цепочками обещаний - PullRequest
2 голосов
/ 04 апреля 2019

Я использую cheeriojs для удаления сайта, мне нужно отправить много запросов по нескольким параметрам URL.

минимальный код:

const rp = require('request-promise');
const cheerio = require('cheerio');

[1, 2, 3].forEach(element => {
  url = `https://stackoverflow.com/q=${element}`
  rp(url)
    .then((html) => {
      // Logic code
   })
})

Я хотел бы установить таймаут между каждым запросом, как мы можем его определить?

Ответы [ 4 ]

3 голосов
/ 04 апреля 2019

Я думаю, что наиболее читаемый подход - использовать асинхронную функцию и тайм-аут с обещанием.

function sleep(millis) {
  return new Promise(resolve => setTimeout(resolve, millis));
}
async function process(list) {
  for (const item of list) {
    const html = await rp(`https://stackoverflow.com/q=${item}`);
    ... do stuff
    await sleep(1000);
  }
}
1 голос
/ 04 апреля 2019

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

const rp = require('request-promise');
const cheerio = require('cheerio');

[1, 2, 3].reduce((p, element) => {
  url = `https://stackoverflow.com/q=${element}`
  return p
    .then(() => rp(url))
    .then((html) => {
      // Logic code
    });
}, Promise.resolve())

Это создает цепочку, эквивалентную

rp(url1)
  .then(html => ...)
  .then(() => rp(url1))
  .then(html => ...)
  .then(() => rp(url2))
  .then(html => ...)

Чтобы добавить задержку, мы определяем функцию, которая возвращает функцию, котораявозвращает обещание, которое разрешается через x миллисекунд через setTimeout:

function wait(x) {
  return () => new Promise(resolve => setTimeout(resolve, x));
}

Теперь мы можем добавить это в нашу цепочку (я заменяю rp чем-то, что выполняется здесь):

function wait(x) {
  return () => new Promise(resolve => setTimeout(resolve, x));
}

[1, 2, 3].reduce((p, element) => {
  const url = `https://stackoverflow.com/q=${element}`
  return p
    .then(() => Promise.resolve(url))
    .then((html) => {
      console.log(`Fetched ${html}`);
    })
    .then(wait(2000));
}, Promise.resolve())
0 голосов
/ 04 апреля 2019

Вы можете использовать индексный аргумент forEach в качестве множителя для задержки тайм-аута

const delay = 1000

[1, 2, 3].forEach((element, i) => {
    url = `https://stackoverflow.com/q=${element}`
    setTimeout(() => {
       rp(url)
           .then((html) => {
            // Logic code
           })
    }, i * delay);

})
0 голосов
/ 04 апреля 2019

Если вы хотите использовать оператор forEach, используйте мой первый код.Если вам это не важно, посмотрите мой второй (более простой) рабочий пример, основанный на ответе @ JFord.

Демонстрация RunKit с forEach

RunKitдемо с for item of list

Примечание: код исправлен для правильной работы

forEach пример

const rp = require('request-promise')
const cheerio = require('cheerio')

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function forEachAsync(arr, fn) {
  for (var i = 0; i < arr.length; i++) {
    await fn(arr[i])
  }
}

async function fetchUrls() {
  await forEachAsync([55505362, 55505363, 55505364], async element => {
    await sleep(2000)
    console.log('been 2000 seconds')
    var url = `https://stackoverflow.com/questions/${element}`
    await rp(url)
      .then(html => {
        console.log(html)
      })
      .catch(function(e) {
        console.log(e.message) // "oh, no!"
      })
  })
}

fetchUrls()

for item of list пример

Это рабочий пример, основанный на ответе @JFord, но дополнительно обрабатывающий ошибки.

const rp = require('request-promise')
const cheerio = require('cheerio')

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function fetchUrls(list) {
  for (const item of list) {
    const html = await rp(`https://stackoverflow.com/q=${item}`).catch(function(e) {
        console.log(e.message) // There's an error
    })
    console.log("html: " + html)
    await sleep(2000);
  }
}

fetchUrls([1,2,3])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...