2016-12-14 23 views
0

我正在开发一个应用程序NodeJSExpress。此应用程序的目标是提供从多个不同的API端点获取的数据,全部在一个页面中提供。Express - 来自不同端点的多个异步请求

不幸的是,我与NodeJSExpress相对较新,但已经做了一些研究,我知道,你可以用 async模块多asyncronous请求。但是,我不太清楚如何解决这个问题,需要您的帮助才能让我回到赛道上。

我需要提供两个异步请求来获取所有预期的数据,并最终将它们作为一个JSON链接在一起。该requets如下:

请求1 - 今晚的比赛

首先,我需要今晚(http://exampleapi.com/api/v1/schedule) 输出JSON数据的预定游戏从这个API端点如下:

{ 
    "date": "2016-12-15", 
    "totalGames": 3, 
    "games": [ 
    { 
     "id": 1, 
     "link": "/api/v1/game/1" 
    }, 
    { 
     "id": 2, 
     "link": "/api/v1/game/2" 
    }, 
    { 
     "id": 3, 
     "link": "/api/v1/game/3" 
    } 
    ] 
} 

在下面,从我的文件中有一条路径以上面解释的方式输出提取的JSON

附注/问题:虽然for循环迭代3次以上,但第一个对象将被输出三次而不是三个不同的对象。

server.js

router.get('/test/schedule_test', function(req, res) { 

    res.contentType('application/json'); // content type of the response object 
    var url = 'http://exampleapi.com/api/v1/schedule'; // url of the api endpoint 

    // make an request to the endpoint 
    request(url, function (error, response, body) { 

     // If the request was successfully made 
     if (!error && response.statusCode == 200) { 

      var body = JSON.parse(body); 
      var schedule, totalGames, date, games = [], id, link, game; 

      // Schedule object 
      schedule = { 
       "totalGames": totalGames, 
       "date": date, 
       "games": games 
      }; 
      schedule.totalGames = body.totalGames; 
      schedule.date = body.dates[0].date; 
      game = {"id": id, "link": link}; 

      for(var i = 0; i < schedule.totalGames; i++) { 
       // Here's the part where I think I've made some mistakes and why it outputs a single object over so many times the value of "totalGames" is. 
       game.id = body.dates[0].games[i].gamePk; 
       game.link = body.dates[0].games[i].link; 

       games.push({ 
        "game": game 
       }); 
      } 
      res.status(200).json(schedule); 

     } else { 
      res.status(404).json({"error": true}); 
     } 
    }); 
}); 

接下来,我需要为每个被链接的属性值提供的链接的异步请求获取各参赛队的队相关的数据。

请求2 - 团队相关的数据

从这个API端点

产出预期JSON如下:

{ 
    "gameData": { 
    "teams": { 
     "away": { 
     "link": "/api/v1/teams/1", 
     "name": "Example team 1", 
     "abbreviation": "EXT1" 
     }, 

     "home": { 
     "link": "/api/v1/teams/2", 
     "name": "Example team 2", 
     "abbreviation": "EXT2"  
     } 
    }, 
    "venue": { 
     "name": "Georgestown Palace, Manitoba" 
    } 
    } 
} 

下面,有从我的文件,做输出路线所取得的JSON以上面解释的方式。

server.js

router.get('/test/team_test', function(req, res) { 

    // Note that these urls should be generated dynamically from the previous request 
    var urls = [ 
     'http://exampleapi.com/api/v1/teams/1', 
     'http://exampleapi.com/api/v1/teams/2' 
    ]; 

    async.map(urls, function(url, callback) { 
     // iterator function 
     request(url, function (error, response, body) { 

      if (!error && response.statusCode == 200) { 
       // do any further processing of the data here 
       var body = JSON.parse(body); 
       var teams; 

       // Away team 
       var away_link, away_name, away_abbr; 
       var away = {"link": away_link, "name": away_name, "abbreviation": away_abbr}; 

       var away_link = body.gameData.teams.away.link; 
       away.link = away_link; 

       var away_name = body.gameData.teams.away.name; 
       away.name = away_name; 

       var abbreviation = body.gameData.teams.away.abbreviation; 
       away.abbrreviation = abbreviation; 

       // Home team 
       var home_link, home_name, home_abbr; 
       var home = {"link": home_link, "name": home_name, "abbreviation": home_abbr}; 

       var home_link = body.gameData.teams.home.link; 
       home.link = home_link; 

       var home_name = body.gameData.teams.home.name; 
       home.name = home_name; 

       var home_abbreviation = body.gameData.teams.home.abbreviation; 
       home.abbreviation = home_abbreviation; 

       var arena = body.gameData.venue.name; 

       teams = { 
        "teams": { 
         "away": away, 
         "home": home 
        }, 
        "played_at": arena 

       }; 

       callback(null, teams); 

      } else { 
       callback(error || response.statusCode); 
      } 
     }); 
    }, function(err, results) { 

     // completion function 
     if (!err) { 
      res.contentType('application/json'); 
      res.status(200).json(results); 
     } else { 
      // handle error here 
      console.log(err); 
     } 
    }); 
}); 

预期结果

最后,我需要加入这两个不同的输出到一个JSON输出。预期结果如下所示:

{ 
    "date": "2016-12-15", 
    "totalGames": 3, 
    "games": [ 
    { 
     // #1 joined object 

     // data from the first api request 
     "id": 1, 
     "link": "/api/v1/game/1", 

     // data from the second api request 
     "teams": { 
      "away": { 
      "link": "/api/v1/teams/1", 
      "name": "Example team 1", 
      "abbreviation": "EXT1" 
      }, 
      "home": { 
      "link": "/api/v1/teams/2", 
      "name": "Example team 2", 
      "abbreviation": "EXT2"  
      } 
     }, 
     "venue": { 
      "name": "Georgestown Palace, Manitoba" 
     } 
    }, 


    { 
     // #2 joined object 
     "id": 2, 
     "link": "/api/v1/game/3", 
     "teams": { 
      "away": { 
      "link": "/api/v1/teams/3", 
      "name": "Example team 3", 
      "abbreviation": "EXT3" 
      }, 
      "home": { 
      "link": "/api/v1/teams/4", 
      "name": "Example team 4", 
      "abbreviation": "EXT4"  
      } 
     }, 
     "venue": { 
      "name": "Portsmouth Valley, New Jersey" 
     } 
    }, 

    { 
     // #3 joined object 
     "id": 3, 
     "link": "/api/v1/game/3", 
     "teams": { 
      "away": { 
      "link": "/api/v1/teams/5", 
      "name": "Example team 5", 
      "abbreviation": "EXT5" 
      }, 
      "home": { 
      "link": "/api/v1/teams/6", 
      "name": "Example team 6", 
      "abbreviation": "EXT6"  
      } 
     }, 
     "venue": { 
      "name": "Colorado Springs, Colorado" 
     } 

    } 

    ] 

} 

任何帮助将不胜感激。预先感谢和快乐的编码!

回答

0

为了协调多个异步操作,我强烈建议您使用promise。如果您让每个异步操作都返回一个承诺,那么您可以使用Promise.all()来了解它们何时全部完成,并且可以访问每个异步操作获取的数据。

举例来说,如果你有终点的数组,你想获取的,你可以这样做,像这样的数据:

const request = require('request'); 

// promisify the request module 
function requestAsync(url) { 
    return new Promise(function(resolve, reject) { 
     request(url, function(err, response, body) { 
      if (err) { 
       reject(err); 
      } else if (response.statusCode !== 200) { 
       reject(new Error("response.statusCode = " + response.statusCode)); 
      } else { 
       resolve(body); 
      } 
     }); 
    }); 
} 


function getData(endpoints) { 
    return Promise.all(endpoints.map(function(url) { 
     return requestAsync(url); 
    })); 
} 

let endpoints = [...]; // multiple endpoints to retrieve data from 
getData(endpoints).then(function(results) { 
    // results array contains all the results you can process here in the 
    // order they appears in the array. 
    // You can now organize the returned data into the final format you want here 
}).catch(function(err) { 
    // error occurred here 
}); 
+0

怎么样的事实:一些端点的URL生成动态的基础上先前请求的链接属性值? –

+0

@B_CooperA - 显然你必须做一些更具体的事情。我不得不明白你想要做什么,因为我没有看到你的问题中的代码所示的情况。我仍然使用承诺来协调异步结果,但是对于您的具体情况还没有一个通用的答案。我回答了你我正在做什么,它是从多个独立端点并行获取数据并使用结果生成一个页面。 – jfriend00