在返回之前从多个HTTP GET请求中获取数据

时间:2018-05-08 01:52:03

标签: javascript node.js

我有以下代码片段接受数据数组,对数组中的每个项执行HTTP GET请求,并在执行提供的回调方法之前将返回的数据加载到新数组中:

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

}

基本上它需要一组像这样的对象:

[
    {
      "username":"user1",
      "blazeId":"guid1"
    },
    {
       "username":"user2",
       "blazeId":"guid2"
    }
]

并返回一个像这样的对象数组:

[
   {
      "username":"user1",
      "data": { /** response data **/ }
   },
   {
      "username":"user2",
      "data": { /** response data **/ }
   }
]

我遇到的问题是,我不知道如何调用提供的回调方法,使代码在执行前等待所有http.get操作完成。

如何达到预期效果?

3 个答案:

答案 0 :(得分:4)

您可以对所有请求使用Promise.all,这些请求一旦解决,就会调用回调:

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

请注意,通过此实现,callbackMethod应接受与您的returnData数组对应的一个参数。

答案 1 :(得分:1)

你可以测试returnData的长度,当它与你拥有它的所有玩家的长度相匹配时,你可以回调。我还建议您查看异步模块https://www.npmjs.com/package/async或转换为使用promise并使用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!
               }                      
           });
       });
   });
}

答案 2 :(得分:1)

使用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
}