2016-12-14 1 views
0

Я разрабатываю приложение с NodeJS и Express. Цель этого приложения - предоставить данные, которые извлекаются из нескольких разных конечных точек API, всего на одной странице.Экспресс - Несколько асинхронных запросов с разных конечных точек

К сожалению, я относительно новый с NodeJS и Express, но уже сделали некоторые исследования, и я знаю, что вы можете сделать несколько запросов с асинхронного модулем async. Тем не менее, я не совсем уверен, как подойти к этой проблеме и вам нужна ваша помощь, чтобы вернуть меня на трассу.

Мне нужно предоставить два асинхронных запроса, чтобы получить все ожидаемые данные и соединить их вместе как один 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 - данные команды, связанные с

Ожидаемое JSON выход из этого API конечной точки выглядит следующим образом:

{ 
    "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.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

насчет того, что некоторые из конечных адресов генерируются динамически на основе значение свойства ссылки предыдущего запроса? –

+0

@B_CooperA - Обидно, вам нужно сделать что-то более конкретное для вашей ситуации. Я должен был бы точно понять, что вы пытаетесь сделать, потому что я не вижу этой ситуации, проиллюстрированной в коде в вашем вопросе. Я по-прежнему буду использовать обещания для координации асинхронных результатов, но для вашей конкретной ситуации нет общего ответа. Я дал ответ за то, что я, хотя вы делали, который собирал данные из нескольких независимых конечных точек параллельно и использовал результаты для создания страницы. – jfriend00

Смежные вопросы