Как выполнить функцию после того, как будет переменная получит своё значение через fetch?
Каждому элементу массива "contents" (в цикле) присваивается то значение, которое приходит через fetch-запрос. Как сделать так, чтобы следующая за этим циклом функция начинала работать только после того, как будет выполнен цикл и все элементы массива "contents" получат своё значение?
function setContents() {
for (i = 0; i < list.length; i++) {
contents[i] = getContent(list[i].link)
}
nextFunction() // Выполняется преждевременно, когда contents ещё "не готов"
}
async function getContent(link) {
let response = await fetch('/folder/' + link + '.json')
contents1[i] = await response.json()
}
Этот вопрос решается через вызов следующей функции через указанное время, но нужно, чтобы выполнение происходило "как только, так сразу".
setTimeout('nextFunction()', 10000)
Ответы (2 шт):
Вам нужно использовать async/await в функции, где вы вызываете функцию getContent. В самой функции getContent это необязательно.
То есть, в вашем случае можно сделать так:
async function setContents() {
for (i = 0; i < list.length; i++) {
contents[i] = await getContent(list[i].link)
}
nextFunction() // Будет выполняться после того, как цикл закончится и все значения будут получены
}
function getContent(link) {
let response = await fetch('/folder/' + link + '.json')
contents1[i] = await response.json()
}
Заметьте, await вызывается не перед contents[i] = , а перед getContent(...).
В этом случае, JavaScript будет ждать выполнения функции await getContent(), а не оставит её выполняться синхронно в итерации цикла for.
Для этого случая, я составил небольшой пример, и сам убедился, что это работает:
function nextFunction() {
console.log("Следующая функция"); // Это будет выводиться ПОСЛЕ того, как цикл закончится
}
// Для корректной работы тут необходим async
async function iterateCycle() {
// Тут надо вставить число итераций, необходимое вам
// ^^^
for (i = 0; i < 5; i++) {
// А вот тут необходимо вставить await перед вызовом функции
console.log(await oneIteration(i)); //-->1 итерация
//-->2 итерация
// и т.д.
}
nextFunction(); // Будет выполняться после завершения цикла for
}
// Заметьте, тут необязательны операторы async/await
function oneIteration(iteration) {
return new Promise((resolve, reject) => {
// Будет возвращаться каждую итерацию через 1 секунду после вызова функции
setTimeout(() => {
resolve(iteration + " итерация.");
}, 1000);
});
}
// В конце концов, вызываем цикл
iterateCycle();
Как сделать так, чтобы следующая за этим циклом функция начинала работать только после того, как будет выполнен цикл и все элементы массива "contents" получат своё значение?
Например можно использовать асинхронность более "широко" - вот таким образом...
function setContents() {
const a = []
for (let i = 0; i < list.length; i++) {
a.push(getContent(list[i].link, i))
}
Promise.all(a)
.then(_ => nextFunction())
.catch(console.error)
}
async function getContent(link, i) {
let response = await fetch('/folder/' + link + '.json')
contents1[i] = await response.json()
}