ravibhagw
ravibhagw

Reputation: 1740

Get data from multiple HTTP GET requests before returning

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

Answers (3)

Felipe Micali
Felipe Micali

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

generalhenry
generalhenry

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

CertainPerformance
CertainPerformance

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

Related Questions