#javascript #async-await #promise
Вопрос:
Я очень смущен тем, почему моя асинхронная функция не ждет, прежде чем запускать код внутри .затем
Например, карты должны представлять собой массив из 102 элементов. Однако console.log(карты.длина) показывает 0. Кроме того, последнее .затем освобождается от ответственности до того, как какой-либо элемент будет помещен в карты.
React.useEffect(() => {
// if (!cards.length) {
//https://api.pokemontcg.io/v2/cards?q=set.id:base1
async function fetchCards() {
const response = await fetch('https://api.pokemontcg.io/v2/cards?q=set.id:base1', {
mode: 'cors',
headers: {
'X-Api-key': '22173ccf-376e-4d12-8d50-8b25df6a8e13',
},
})
.then((res) => res.json())
.then((data) => {
console.log(data.data);
setCards(data.data);
console.log(cards.length);
})
.then(() => {
updateDeck(getRandom(cards, 4));
});
}
// }
fetchCards()
}, []);
Комментарии:
1. Основная часть fetchCards ничего не возвращает, поэтому первая
.then()
уже не получает данных для работы. Вместоconst response = await fetch(...)
того, чтобы простоreturn fetch(...)
. На самом деле, зачем вообще нужны карточки? Просто имейтеfetch(url, ...).then(response => response.json()).then(......)
, не нужно объявлять и вызывать, у вас уже есть цепочка обещаний, начиная с fetch.2. @Mike’Pomax’Camermans Я отредактировал код, но его длина по-прежнему равна 0.
3. Откуда это
cards
берется? Вашthen
аргумент называетсяdata
«нетcards
«, поэтому вы не показываете весь свой код , и я не собираюсь гадать, что делает остальное. Если setCards является функцией состояния, то да, очевидно, что связаннаяcards
функция не будет обновлена в следующей строке: она будет обновлена при следующем вызове рендеринга, а не раньше. Вот как обновления состояния работают в React.4. Простите мое полное невежество. вы имеете в виду, что я должен обернуть (res.json()) так, чтобы вернуть его?
5. карты, поступающие из инициализации useState const [карты, setCards] = React.useState([]);
Ответ №1:
- Вы не должны путать ваши
async/await
s сthen
обратными вызовами. - Используйте новый
useEffect
, чтобы проверить, когдаcards
изменения вызовут вашуupdateDeck
функцию.setCards
является асинхронным процессом, поэтому новое состояние будет доступно не сразу после его установки. Вот почему требуется дополнительная платаuseEffect
, когда состояние действительно меняется.
Вот сокращенный пример:
useEffect(() => {
async function fetchCards() {
const res = await fetch(url, params);
const data = await res.json();
setCards(data.data);
}
fetchCards();
}, []);
useEffect(() => {
if (cards.length) updateDeck(getRandom(cards, 4));
}, [cards]);
Комментарии:
1. Я об этом не подумал! Я попробую это сделать. Однако я отредактировал код, чтобы удалить ожидание/асинхронность, и оставил только .затем. Однако все равно не повезло. Есть идеи, почему?
2.
setCards
является асинхронным, поэтому новое состояние не будет доступно сразу же после его установки, поэтомуuseEffect
для того, когда состояние изменится, требуется дополнительный параметр.3. Должен ли я также использовать любую функцию, которую я хочу запустить на картах, во втором эффекте использования?
4. @капитан: К вашему сведению, я откатил вашу правку. Переполнение стека немного отличается от других форумов, которые вы, возможно, использовали, в том, что цель состоит в создании страниц с вопросами и ответами, которые полезны другим людям; поэтому, как только ответ опубликован, вы не должны редактировать свой вопрос, чтобы признать его недействительным. (Я имею в виду, что если ответ был результатом неправильного понимания вашего вопроса, то можно отредактировать вопрос, чтобы уточнить; но если вопрос касается ошибки, и ответ показывает, как ее исправить, то вы не должны редактировать вопрос, чтобы исправить эту ошибку и спросить о новой проблеме.)
5. второй эффект использования вызывается первым рендером и выдает ошибку, потому что карты пусты! есть ли способ заставить его ждать без условного условия?