在循环Node.js中返回API请求

时间:2019-08-23 01:19:19

标签: node.js http callback request

我有一个约有15个项目的循环,每次循环迭代时都需要进行两个api调用。因此,我需要在循环内发出API请求,然后在循环继续进行之前进行一些简单的计算。

假设我有一个名为getFlightData的函数,该函数带有3个参数-出发城市,到达城市和日期。该函数需要发出API请求,然后从API调用返回JSON。

请参阅下面的代码。

const airportsList = [
    "SFO",
    "SEA",
    "JFK",
    "YTZ"
 ]

   for (var i = 0; i < airportsList.length; i++) {
     // loop through the airports

     var departingFlightCost, returningFlightCost;
     getFlightData("MEX", airportsList[i], date1);
     getFlightData(airportsList[i],"MEX", date2);
   }


 function getFlightData(departingCity, arrivingCity, date) {
    var options = {
      method: 'GET',
      url: 'https://apidojo-kayak-v1.p.rapidapi.com/flights/create-session',
      qs: {
        origin1: departingCity,
        destination1: arrivingCity,
        departdate1: date, //'2019-12-20',
        cabin: 'e',
        currency: 'USD',
        adults: '1',
        bags: '0'
      },
      headers: {
        'x-rapidapi-host': 'apidojo-kayak-v1.p.rapidapi.com',
        'x-rapidapi-key': API_KEY
      }
    };
    request(options, function (error, response, body) {
      const flightData = body;
    });
  }

每次循环遍历一个城市时,我需要获取两个API请求的内容,然后在继续之前进行简单的计算。如何最有效地在节点上执行此操作?

1 个答案:

答案 0 :(得分:1)

您可以尝试以下方法:

const getFlightData = (departingCity, arrivingCity, date) => new Promise((resolve, reject) => {
  const options = {};

  request(options, (error, res) => {
    if (error) {
      return reject(error);
    }

    return resolve(res);
  });
});

const airportsList = [
  "SFO",
  "SEA",
  "JFK",
  "YTZ"
];

// things will run in parallel
for (let i = 0; i < airportsList.length; i++) {
  const date1 = new Date();
  const date2 = new Date();

  const tasks = [
    getFlightData("MEX", airportsList[i], date1),
    getFlightData(airportsList[i], "MEX", date2)
  ];

  // wait 2 tasks completed and handle
  Promise.all(tasks)
    .then(responses => {
      const res1 = responses[0];
      const res2 = responses[1];

      // continue doing something here
    })
    .catch(error => {
      // handle error here
    })
}

或者,如果您希望一切逐步进行,则可以使用以下功能替换for loop

const syncLoop = i => {
  const date1 = new Date();
  const date2 = new Date();

  const tasks = [
    getFlightData("MEX", airportsList[i], date1),
    getFlightData(airportsList[i], "MEX", date2)
  ];

  // wait 2 tasks completed and handle
  Promise.all(tasks)
    .then(responses => {
      const res1 = responses[0];
      const res2 = responses[1];

      // continue doing something here

      // schedule a new function
      syncLoop(i + 1);
    })
    .catch(error => {
      // handle error here
    })
};

syncLoop(0);

如果您在完成所有异步任务后需要做一些事情:

const allTasks = [];
// things will run in parallel
for (let i = 0; i < airportsList.length; i++) {
  const date1 = new Date();
  const date2 = new Date();

  const tasks = [
    getFlightData("MEX", airportsList[i], date1),
    getFlightData(airportsList[i], "MEX", date2)
  ];

  // wait 2 tasks completed and handle
  allTasks.push(Promise.all(tasks)
    .then(responses => {
      const res1 = responses[0];
      const res2 = responses[1];

      // continue doing something here

      // remember to return something here
      // things will appear in the below Promise.all
      return res1;
    })
    .catch(error => {
      // handle error here
    })
  );
}

Promise.all(allTasks)
  .then(allResponses => {
    // do something when all of async tasks above were done
  })
  .catch(error => {
    // handle error here
  });