Я пытаюсь использовать 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 для продолжения выполнения.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Что-то вроде этого может работать:
...
promisesArray = []
ids.forEach(element => {
promisesArray.push(getMods(element))
});
Promise.all(promisesArray).then(() => {
console.info("download finished");
});
Вы абсолютно правы! Я отредактировал ответ.
Поскольку вы запускаете 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")
Сделайте массив обещаний, затем используйте
Promise.all(), чтобы распечатать результаты по порядку.