如何遍历URL数组并等待响应,然后再移至下一个

时间:2020-07-29 21:47:14

标签: javascript node.js express asynchronous async-await

我有900多个URL列表,我想获取它们以进行日常cron作业,并且我正在使用Express.js。我在网上检查了一种方法和ran across this jsinclair page,因此我尝试实现该方法,但到目前为止没有任何效果。 假设这是我的清单:

let arrayOfAsyncTasks = [
    {task: 'fetch', url: 'http://thatapi.com/api1/thing'},
    {task: 'wait', duration: 60000 },
    {task: 'fetch', url: 'http://thatapi.com/api2/thing'},
    {task: 'wait', duration: 60000 },
    ...
]

我试图做的是使用Array.reduce强制迭代在开始获取下一个URL之前坚持60秒的延迟,就像这样:

const starterPromise = Promise.resolve(null);
const log = result => console.log(result);

arrayOfAsyncTasks.reduce(
    (p, spec) => p.then(() => {
        runTask(spec)
        .then(result => {
            console.log(`Inside reduce function after runTask! result: `, result)
            log(result)
        })
     })
     .catch(err => console.log(`err: `, err) ),
     starterPromise
    );

这是辅助函数:

function asyncTimeout(delay) {
    console.log(`inside asyncTimeout! delay: `, delay);
    return (new Promise(resolve => {setTimeout(() => resolve(delay), delay)}))
        .then(d => `Waited ${d} seconds`);
}

function asyncFetch(url) {
    console.log(`inside asyncFetch!  url: `, url);
    scrapeEbayCategory(url)
        .then(response => (response.json()))
        .then(text => `Fetched ${url}, and got back ${text}` );
}

function runTask(spec) {
    return (spec.task === 'wait')
    ? asyncTimeout(spec.duration)
    : asyncFetch(spec.url);
}

结果是它移到下一个项目的速度太快,然后在控制台中显示了多个延迟完成的控制台日志:

Waited 60000 seconds
Inside reduce function after runTask! result:  Waited 60000 seconds
Waited 60000 seconds
Inside reduce function after runTask! result:  Waited 60000 seconds
Waited 60000 seconds
Inside reduce function after runTask! result:  Waited 60000 seconds
Waited 60000 seconds
Inside reduce function after runTask! result:  Waited 60000 seconds
Waited 60000 seconds
Inside reduce function after runTask! result:  Waited 60000 seconds
Waited 60000 seconds
Inside reduce function after runTask! result:  Waited 60000 seconds
Waited 60000 seconds
Inside reduce function after runTask! result:  Waited 60000 seconds
Waited 60000 seconds
Inside reduce function after runTask! result:  Waited 60000 seconds
...

我想要的结果是它等待一项内容的获取完成,然后再获取另一项内容。

2 个答案:

答案 0 :(得分:1)

似乎过于复杂。

Id将其重写以遍历数组,并基于task在异步/等待中进行提取或等待

//
const sleep = ms => new Promise(r => setTimeout(r, ms));

let arrayOfAsyncTasks = [{
    task: 'fetch',
    url: 'http://thatapi.com/api1/thing'
  },
  {
    task: 'wait',
    duration: 60000
  },
  {
    task: 'fetch',
    url: 'http://thatapi.com/api2/thing'
  },
  {
    task: 'wait',
    duration: 60000
  }
]

;(async() => {

  for (let task of arrayOfAsyncTasks) {
    console.log('running', task)
    if (task.task === 'wait') {
      await sleep(task.duration)
    }

    if (task.task === 'fetch') {
      try {
        // await fetch(task.url)....
      } catch (e) {}
    }
  }
})()

答案 1 :(得分:0)

handleTask = async function(task) {
  if (task.task === 'fetch') {
    // make API call here
    return APICALL(task.url)
  } else if (task.task === 'wait') {
    // sleep here
    await sleep(task.duration)
  }
}

let arrayOfAsyncTasks = [
    {task: 'fetch', url: 'http://thatapi.com/api1/thing'},
    {task: 'wait', duration: 60000 },
    {task: 'fetch', url: 'http://thatapi.com/api2/thing'},
    {task: 'wait', duration: 60000 },
    ...
]

await Promise.each(arrayOfAsyncTasks, async(task) => {
  return handleTask(task)
})