Дождитесь завершения вызовов api и затем верните результирующий Nodejs

#javascript #node.js #express #asynchronous

#javascript #node.js #выразить #асинхронный

Вопрос:

Я пытаюсь выполнить вызов api несколько раз, в том числе для:

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

как вы можете видеть, я помещаю результат каждого вызова в массив с именем finalMovies,
и затем пытаетесь вернуть результат следующим образом:

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

Проблема в том, что я получаю массив только с первым вызовом в нем.

Как я могу изменить свой код, чтобы я мог дождаться, когда myPromise завершит цикл, а затем вернет массив?.

Спасибо!

Ответ №1:

Обещание разрешается только один раз, поэтому вам нужно разрешить другое обещание для каждого запроса, затем используйте Promise.all для их объединения:

 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(/*...*/);
  

Ответ №2:

Ваш код пытается выполнить асинхронную операцию (вызов API) как синхронную, что невозможно в node.js. Здесь произойдет то, что во время итерации в цикле for запросы к API выполняются с регистрацией обратного вызова, а затем цикл for завершает выполнение и продолжается. Во время выполнения каждого запроса выполняется возврат с кодом ответа.

Правильный способ сделать это, как указано Джонасом в приведенном выше ответе.

Другой альтернативой является использование библиотеки async, которая написана специально для такого рода операций. В асинхронной библиотеке есть функции цикла, такие как each(), eachLimit(), которые можно использовать вместо цикла for в подобных ситуациях.