Jesus Zuñiga
Jesus Zuñiga

Reputation: 135

Wait for api calls to finish and then return the result Nodejs

I'm trying to make an api call several times inide a For:

const myPromise = new Promise(function(resolve, reject) {
  // code here
  for (let i = 0; i < recommendedMovies.length; i++) {
    tmdb.genre.movies(
      recommendedMovies[i].id,
      randomNumber,
      (err, response) => {
        if (!err) {
          finalMovies.push(response.results);
          resolve(finalMovies)
        } else {
          reject('error')
        }
      }
    );
  }     
});

as you can see, i'm pushing each call result into an array called finalMovies, and then trying to return the result as follow:

myPromise
  .then(function whenOk(response) {
    res.json(response)
  })
  .catch(function notOk(err) {
    console.log(err);
  });

The problem is that i'm only getting the array with the first call in it.

How can i change my code so i can wait myPromise to complete the loop and then return the array?.

Thanks!

Upvotes: 1

Views: 2819

Answers (2)

Sahan Maldeniya
Sahan Maldeniya

Reputation: 1046

Your code is trying to execute asynchronous operation (calling an API) as synchronous which is unable in node.js. Here what will happen is the while iterate on the for loop the requests to the API executed with registering a callback and then for loop finish executing and goes on. At the time of each request returns with response code is exited.

Correct way to do this is as mentioned by Jonas in above answer.

Another alternative is to use async library that is written specifically for these kind of operations. With async library there is loop functions such as each(), eachLimit() to use instead of for loop in this kind of situation.

Upvotes: 0

Jonas Wilms
Jonas Wilms

Reputation: 138567

A Promise resolves only once, therefore you need to resolve another promise for each request, then use Promise.all to merge them:

const promises = recommendedMovies.map(({ id }) => new Promise((resolve, reject) =>  {
  tmdb.genre.movies(id, randomNumber, (err, response) => {
    if (!err) {
      resolve(response.results);                 
    } else {
      reject('error')
    }
  });
}));

const result = Promise.all(promises);
result.then(/*...*/).catch(/*...*/);

Upvotes: 5

Related Questions