Reputation: 1740
I have the following snippet of code that accepts an array of data, performs an HTTP GET request for each item in the array, and loads the returned data into a new array before executing a provided callback method:
function(players, callbackMethod) {
var returnData = [];
players.forEach(function(item){
var playerRequestUrl = baseUrl+'/'+platform+'/members/'+item.blazeId+'/stats';
https.get(playerRequestUrl, function(res){
res.on('data', function(chunk){
var playerData = JSON.parse(chunk);
returnData.push({"username":item.username, "data":playerData.raw[item.blazeId]});
//callback here?
});
});
});
}
Essentially it takes an array of objects like this:
[
{
"username":"user1",
"blazeId":"guid1"
},
{
"username":"user2",
"blazeId":"guid2"
}
]
and returns an array of objects like this:
[
{
"username":"user1",
"data": { /** response data **/ }
},
{
"username":"user2",
"data": { /** response data **/ }
}
]
The issue I have is that I don't know how to invoke the supplied callback method in such a way that the code waits until all http.get
operations have completed before executing.
How can I achieve the expected results?
Upvotes: 0
Views: 79
Reputation: 847
use async + promises:
function requestPlayer (item, url) {
return new Promise ((resolve, reject) => {
https.get(playerRequestUrl, function(res){
res.on('data', function(chunk){
var playerData = JSON.parse(chunk);
return resolve({"username":item.username, "data":playerData.raw[item.blazeId]})
});
});
})
}
async function myFunction (players) {
var returnData = []
players.forEach(function(item){
returnData.push(requestPlayer(item, baseUrl+'/'+platform+'/members/'+item.blazeId+'/stats'))
})
var res = await Promise.all(returnData)
// do whatever you want with your array of responses
}
Upvotes: 1
Reputation: 17319
You can test length of returnData, when it matches the length of the players you have it all and you can callback. I also recomend taking a look at the async module https://www.npmjs.com/package/async or taking at converting to using promises and using Promise.all
function(players, callbackMethod) {
var returnData = [];
players.forEach(function(item){
var playerRequestUrl = baseUrl+'/'+platform+'/members/'+item.blazeId+'/stats';
https.get(playerRequestUrl, function(res){
res.on('data', function(chunk){
var playerData = JSON.parse(chunk);
returnData.push({"username":item.username, "data":playerData.raw[item.blazeId]});
if (returnData.length === players.length) {
//callback here!
}
});
});
});
}
Upvotes: 1
Reputation: 370639
You can use Promise.all
over all requests that, once resolved, calls the callback:
function getAllPlayers(players, callbackMethod) {
Promise.all(players.map((item) => {
const playerRequestUrl = baseUrl + '/' + platform + '/members/' + item.blazeId + '/stats';
return new Promise((resolve) => {
https.get(playerRequestUrl, function(res) {
res.on('data', function(chunk) {
const playerData = JSON.parse(chunk);
resolve({
"username": item.username,
"data": playerData.raw[item.blazeId]
});
});
});
});
}))
.then(callbackMethod)
}
Note that with this implementation, callbackMethod
should accept one argument corresponding to your returnData
array.
Upvotes: 4