Дождитесь завершения функции выборки

Я пытаюсь использовать curseforge API в проекте с использованием fetch в nodejs18, это код, который я использую:

ids = ["238222","60089","556448"]

const headers = {
  'Accept':'application/json',
  'x-api-key':'API KEY'
};

function getMods(id){
  fetch("https://api.curseforge.com" + '/v1/mods/' + id,
  {
    method: 'GET',

    headers: headers
  })
  .then(function(res) {
      return res.json();
  }).then(function(body) {
      console.info(body.data.name);
  });
}

ids.forEach(element => {
  getMods(element)
});

//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------

console.info("download finished")

С этим кодом вы хотите напечатать в терминале:

Alex's Delight
Mouse Tweaks
Just Enough Items (JEI)
download finished

но при запуске программы я получаю это в терминале:

download finished
Alex's Delight
Mouse Tweaks
Just Enough Items (JEI)

Это происходит из-за того, что функция выборки является асинхронной, я перепробовал все методы решения этой проблемы, но ни одно из решений мне не нужно.

Я хочу, чтобы программа дождалась завершения foreach и fetch для продолжения выполнения.

Сделайте массив обещаний, затем используйте Promise.all(), чтобы распечатать результаты по порядку.

Barmar 06.02.2023 18:05
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
85
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Что-то вроде этого может работать:

...
promisesArray = []
ids.forEach(element => {
  promisesArray.push(getMods(element))
});

Promise.all(promisesArray).then(() => { 
   console.info("download finished");
 });

Вы абсолютно правы! Я отредактировал ответ.

Stanley Ulili 06.02.2023 18:25

Поскольку вы запускаете nodejs 18, вы можете использовать ожидание верхнего уровня

const ids = ["238222", "60089", "556448"]

const headers = {
  'Accept': 'application/json',
  'x-api-key': 'API KEY'
};

async function getMods(id) {
  await fetch("https://api.curseforge.com" + '/v1/mods/' + id, {
      method: 'GET',

      headers: headers
    })
    .then(res => res.json())
    .then(body => {
      console.info(body.data.name);
    });
}

try {
  await Promise.all(ids.map(id => getMods(id)))

  console.info("download finished")
} catch {
  // Handle error

  console.error("download error")
}
Ответ принят как подходящий

Вот примерно как это делается:

const ids = ["238222","60089","556448"]

const headers = {
  'Accept':'application/json',
  'x-api-key':'API KEY'
};

async function getMods(id){

  const res = await fetch("https://api.curseforge.com" + '/v1/mods/' + id, {
    method: 'GET',
    headers,
  })
  const body = await res.json();
  console.info(body.data.name);
}

async function run() {

  for(const element of ids) {
    await getMods(element);
  }
  console.info("download finished")

}

run();

Если вы хотите загружать моды параллельно, а не по одному, функция run() должна выглядеть следующим образом:

async function run() {

  await Promise.all(
    ids.map(element => getMods(element))
  );
  console.info("download finished")

}

Если вы используете ESM, вы можете избежать функции «запустить» и просто использовать ожидание на верхнем уровне. Чтобы легко воспользоваться этим с узлом, просто сохраните файл с расширением .mjs.

Тогда окончательный код может выглядеть так:

const ids = ["238222","60089","556448"]

const headers = {
  'Accept':'application/json',
  'x-api-key':'API KEY'
};

async function getMods(id){

  const res = await fetch("https://api.curseforge.com" + '/v1/mods/' + id, {
    method: 'GET',
    headers,
  })
  const body = await res.json();
  console.info(body.data.name);
}


await Promise.all(
  ids.map(element => getMods(element))
);
console.info("download finished")

Другие вопросы по теме