Reputation: 25
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
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
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
npm install request-promise
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
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