Rishabh
Rishabh

Reputation: 25

How to wait for asynchronous function to be executed?

I am fetching cricket matches and scores from different http requests. The first one fetch match list(with unique ids) and second one fetch scores using unique id. I need the second http request(data.map function) to be completed, then data variable value to be sent(in res.json without using timeout). I know using Promises/Callbacks, but I am confused with code. Currently using setTimeout to wait, but I dont want to use timeout. Please Help.

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)
    })
})

Expecting output to be cricket matches with their score, but without timeout function, current output is undefined.

Upvotes: 0

Views: 155

Answers (3)

Aviso
Aviso

Reputation: 695

Try wrapping map inside promise like this.


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
            })
        })


    })
})

Upvotes: 1

onuriltan
onuriltan

Reputation: 3898

You should use async/await to wait your requests to finish, so what you can do is, so you need to use request-promise package which supports promises, so you can use async await, see at their documentation here

  1. npm install request-promise
  2. Implement async/await as below
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 })
}

Upvotes: 1

Sven van de Scheur
Sven van de Scheur

Reputation: 1903

Wrap every request in a Promise and chain them.

Psuedo code:

// 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)

Upvotes: 0

Related Questions