如何等待异步函数执行?

时间:2019-08-25 15:26:54

标签: javascript node.js

我正在从不同的HTTP请求中获取板球比赛和比分。第一个获取匹配列表(具有唯一ID),第二个获取得分使用唯一ID。我需要完成第二个http请求(data.map函数),然后发送数据变量值(在res.json中而不使用超时)。我知道使用Promises / Callbacks,但是我对代码感到困惑。当前正在使用setTimeout等待,但是我不想使用超时。请帮忙。

app.get('/api/matches', (req, res) => {
    let url = `http://cricapi.com/api/matches?apikey=${key}`
    request(url, { json: true }, (err, resp, body) => {
        if (err) return res.json({
            error: 1,
            msg: err,
        })
        let data = body.matches.filter(match => {
            return match.matchStarted
        })

        data.map((element, index) => {
            let requrl = `http://cricapi.com/api/cricketScore?apikey=${key}&unique_id=${element.unique_id}`
            request(requrl, { json: true }, (err, resp, body) => {
                element.score = body.score
                data.push(element)
            })
        })

        setTimeout(()=>{
            res.json({
                error: 0,
                matches: data
            })  
        },2000)
    })
})

期望板球的输出与其得分相匹配,但没有超时功能,当前输出不确定。

3 个答案:

答案 0 :(得分:1)

您应该使用async/await等待请求完成,所以您可以做的是,所以您需要使用支持Promise的request-promise包,以便可以使用异步等待,请参阅documentation here

  1. npm install request-promise
  2. 按如下所示实施异步/等待
const request = require('request-promise');

app.get('/api/matches', async (req, res) => {
  let url = `http://cricapi.com/api/matches?apikey=${key}`
  let { response, body } = await request({ uri: url, method: 'GET' })
  if (response.statusCode !== 200){
   return res.json({ error: 1, msg: err,})
  } 

  let data = body.matches.filter(match => {
         return match.matchStarted
  })
  await Promise.all(data.map(async (element, index) => {
    let { response, body } = await request({ uri: url, method: 'GET' })
    element.score = body.score
    data.push(element)
  }))
  return res.json({ error: 0, matches: data })
}

答案 1 :(得分:1)

尝试像这样在诺言中包装地图。


app.get('/api/matches', (req, res) => {
    let url = `http://cricapi.com/api/matches?apikey=${key}`
    request(url, { json: true }, (err, resp, body) => {
        if (err) return res.json({
            error: 1,
            msg: err,
        })
        let data = body.matches.filter(match => {
            return match.matchStarted
        })

        let newData = data.map((element, index) => {
            return new Promise((resolve, reject) => {
                let requrl = `http://cricapi.com/api/cricketScore?apikey=${key}&unique_id=${element.unique_id}`
                request(requrl, { json: true }, (err, resp, body) => {
                    element.score = body.score
                    resolve(element);
                })
            });

        })


        Promise.all(newData).then(data => {
            res.json({
                error: 0,
                matches: data
            })
        })


    })
})

答案 2 :(得分:0)

将每个请求包装在Promise中,并将它们链接起来。

伪代码:

// Promise for match
const getMatch = new Promise((resolve, reject) => {
    // Do request, call resolve (or reject) when completed.
    request(url, resolve);
}); 


// Promise for score
const getScore(id) = new Promise((resolve, reject) => {
    // Do request, call resolve (or reject) when completed.
    request(url, resolve);
}); 

// Chain promises
getMatch()
    .then(match => getScore(match))
    .then(profit => console.log(profit)
    .catch(error => console.warn(error)