Как дождаться окончания цикла с асинхронными запросами в node.js? - PullRequest
0 голосов
/ 09 октября 2018

Я хочу сделать несколько запросов в node.js, чтобы получить пару внешних ответов API, чтобы объединить их в один массив.Я использую цикл для достижения этой цели.Вот мой код:

res.setHeader('Content-Type', 'application/json');
const sub = req.query.days_subtract;
const enddate = req.query.end_date; 

var array = [];

for (var i = 0; i < sub; i++) {
  request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY", function(error, response, body) {
    array.push(body); 
    // console.log(body);
  });
}
res.send(array);

, но этот фрагмент кода возвращает [] все время.Я знаю, что это потому, что цикл for только запускает эти асинхронные запросы, но не ожидает их завершения.Я пытался использовать async / await, но это тоже не сработало.Итак, как ждать, пока этот цикл завершит получение запросов и завершит их отправку в массив, чтобы его можно было показать пользователям?

Ответы [ 4 ]

0 голосов
/ 09 октября 2018

Как уже говорили другие, вам, вероятно, следует использовать Promise для своего асинхронного кода, а синтаксис async / await очень разборчив.

Однако вы, похоже, предпочитаете использовать обратные вызовы.В этом случае вы могли бы написать свой код следующим образом:

res.setHeader('Content-Type', 'application/json');
const sub = req.query.days_subtract;
const enddate = req.query.end_date; 

var array = [];
var resultsCount = 0;

for (var i = 0; i < sub; i++) {
  request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY", function(error, response, body) {
    if (error) { res.status(500) }
    array[i] = body
    // console.log(body);
    resultCount++;
    if (resultCount === sub) {
      res.send(array);
    }
  });
}

По сути, идея состоит в том, чтобы вызывать метод res.send только после того, как все запросы вернут свой результат.

0 голосов
/ 09 октября 2018

Для вашего случая использования await с Promise.all, вероятно, самый эффективный способ сделать это.Ваш код должен выглядеть примерно так:

res.setHeader('Content-Type', 'application/json');
const sub = req.query.days_subtract;
const enddate = req.query.end_date;

var promiseArray = [];

for (var i = 0; i < sub; i++) {
    promiseArray.push(new Promise((resolve, reject) => 
        request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY", function(error, response, body) {
        if (err) reject(err);
        resolve(body)
    })))
}
res.send(await Promise.all(promiseArray));
0 голосов
/ 09 октября 2018

Используйте что-то вроде запрос-обещание .Если вы ожидаете каждый запрос в цикле for, то все запросы выполняются последовательно.Если каждый запрос независим и его не нужно выполнять один за другим, это неэффективно.Лучший способ справиться с чем-то подобным - это сделать их все параллельно, а затем ждать их завершения.Это делается путем создания массива обещаний запросов и последующего использования await Promise.all(promiseArray) для ожидания разрешения всех обещаний.

var promises = [];

for (var i = 0; i < sub; i++) {
  const promise = request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY");
  promises.push(promise);
}

const array = await Promisea.all(promises);
0 голосов
/ 09 октября 2018

Чтобы использовать async / await, вам нужно использовать HTTP-библиотеку, которая возвращает обещания, а не обратные вызовы.

Стоит использовать библиотеку, которая может это сделать.Хорошим вариантом для другой библиотеки является node-fetch, который эффективно реализует «Fetch API», реализованный браузерами.

После этого вы можете просто await fetch(url).

async / await работать такну и это становится настолько распространенным явлением, что я настоятельно рекомендую переключиться на фреймворки и библиотеки, которые рассматривают его как первоклассного гражданина, а не запоздалая мысльЭто включает в себя Express, которая также является библиотекой на основе обратного вызова, а не библиотекой на основе Promise.Но это немного не по теме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...