Superagent async嵌套循环http调用

时间:2018-03-21 09:30:03

标签: javascript node.js async-await

我试图使用superagent来获取网页中的链接,并从该链接中的另一个表中获取值。

到目前为止,我已经在console.log中成功了,但是在尝试使用异步调用返回对象时遇到了问题。

await request函数中的第一个getData工作正常,getOrder内另一个也在cheerio .each内的工作不能按预期工作。

在这里提到cheerio因为我不确定导致问题的原因

这是我迄今为止所做的事情

const request = require('superagent');
const cheerio = require('cheerio')

server.get('/crawler', (req, res) => {
  const data = await getData(url)
  console.log('data loaded ')
  res.send(data)
})

const getData = async (url) => {
  console.log('before root')
  const result = await request.get(url).set(header)
  console.log('after root')

  const $ = cheerio.load(result.text);

  let p = Promise.resolve();
  $('table').first().find('tr').each(async (i, row) => {
    p = p.then(async () => {
      console.log('order no', row.orderNo)
      let viewOrder = await getOrder(row.url)
      console.log('after getOrder')

      // .... build data here 

    })
  })
  p.then(() => {
    // ....
    return data
  })
}

const getOrder = async (url) => {
  console.log('before call')
  const result = await request.get(url).set(header)
  // the response return before this line in 1st round of loop 
  console.log('called', url)

  const $ = cheerio.load(result.text);

  let p = Promise.resolve();
  $('table').first().find('tr').each(async (i, row) => {
    p = p.then(async () => {
      // .... build data here
    })

  })
  p.then(() => {
    return data
  })
}

输出

before root
after root
order no 1
before call
data loaded
GET /crawler <<<<<<< res.send here
called ...
after getOrder
order no 2
before call
called ...
after getOrder
before call
order no 3
called ...
after getOrder

它应该是什么

程序应该等待所有请求被调用然后返回响应

2 个答案:

答案 0 :(得分:0)

尝试这种模式:

function doSomething() {
  return () => 
    fetch('/api/something').then(response => response.json())
}

function doSomethingElse() {
  return () => 
    fetch('/api/something').then(response => response.json())
}

function doEverything() {
  return () => Promise.all([
   doSomething(),
   doSomethingElse()
  ]);
}

答案 1 :(得分:0)

经过一些研究后,我发现我需要将该函数包装在Promiseresovle中,以使其与await一起使用

const getData = (url) => {
  return new Promise(async (resolve, reject) => {
    console.log('before root')
    const result = await request.get(url).set(header)
    console.log('after root')

    const $ = cheerio.load(result.text);

    let p = Promise.resolve();
    $(tableSelector).first().find('tr').each(async (i, row) => {
      p = p.then(async () => {
        console.log('order no', row.orderNo)
        let viewOrder = await getOrder(row.url)
        console.log('after getOrder')

        // .... build data here 

      })
    })
    p.then(() => {
      // ....
      resolve(data)
    })
  })
}

const getOrder = async (url) => {
  return new Promise(async (resolve, reject) => {
    console.log('before call')
    const result = await request.get(url).set(header)
    console.log('called', url)

    const $ = cheerio.load(result.text);

    let p = Promise.resolve();
    $(tableSelector).first().find('tr').each(async (i, row) => {
      p = p.then(async () => {
        // .... build data here
      })

    })
    p.then(() => {
      resolve(data)
    })
  })
}