You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么放在.then链中的函数会提前触发?(promise/async/await问题)

问题原因分析
  • 你误以为async函数没有等待.then内部逻辑执行,实际上async已经完整等待了所有链式回调执行完成,问题根源是React的状态更新机制和闭包特性,和异步等待逻辑无关。
  • React的setState(此处为setCards)属于异步批量更新操作,调用后不会立刻修改当前作用域下的cards变量,当前渲染闭包内的cards始终是本次渲染开始时的旧值(也就是你初始化的空数组),所以调用setCards后立刻打印cards.length必然返回0。
  • 最后一个.then回调中读取的cards依旧是当前闭包的旧值,无法获取到刚提交更新的状态,因此会出现“cards被赋值前就执行”的错觉。
修正方案

方案1:直接使用接口返回的data数据执行后续逻辑,不需要依赖状态更新

React.useEffect(() => {
  async function fetchCards() {
    try {
      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',
        },
      })
      const data = await response.json()
      const cardList = data.data
      console.log(cardList.length) // 此处可拿到正确的数组长度
      setCards(cardList)
      updateDeck(getRandom(cardList, 4)) // 直接用接口返回的数组执行后续逻辑,不需要等状态更新
    } catch (err) {
      console.error('卡片请求失败', err)
    }
  }
  fetchCards()
}, []);

方案2:如果后续逻辑必须依赖更新后的cards状态,单独加useEffect监听

// 卡片请求逻辑
React.useEffect(() => {
  async function fetchCards() {
    try {
      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',
        },
      })
      const data = await response.json()
      setCards(data.data)
    } catch (err) {
      console.error('卡片请求失败', err)
    }
  }
  fetchCards()
}, []);

// 监听cards状态变化,状态更新后执行后续逻辑
React.useEffect(() => {
  if (cards.length) {
    console.log(cards.length) // 此处可拿到正确的数组长度
    updateDeck(getRandom(cards, 4))
  }
}, [cards])

内容的提问来源于stack exchange,提问作者captaincustard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 07:45:03