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

NextJS中React Query useQuery无法返回异步API调用结果的问题

问题解决思路与代码修正

核心问题

你的代码关键bug是**forEach无法等待异步函数执行完成**:

  • 在snapshot.forEach(async (doc) => {})中编写异步逻辑时,forEach会直接遍历所有文档,不会等待每个异步请求结束就执行后续代码,导致retArr还没被填充就提前返回。
  • 带Promise的版本里,retArr存的是价格数值而非Promise,Promise.all(retArr)完全起不到等待异步操作的作用。

修正后的代码

const fetchListDocs = async () => {
  try {
    const queryCollection = query(collection(db, loc));
    const snapshot = await getDocs(queryCollection);
    
    const tickerPriceMap = new Map();
    // 1. 将snapshot转为数组,用map生成所有需要执行的Promise
    const pricePromises = snapshot.docs.map(async (doc) => {
      const docTicker = doc.data().stockTicker;
      
      // 避免重复请求相同ticker的价格
      if (!tickerPriceMap.has(docTicker)) {
        const newPrice = await getStockPrice(docTicker);
        const currentPrice = parseFloat(newPrice.toFixed(2));
        tickerPriceMap.set(docTicker, currentPrice);
      }
    });

    // 2. 等待所有异步请求完成
    await Promise.all(pricePromises);
    
    // 3. 将Map中的价格转为数组返回
    return Array.from(tickerPriceMap.values());
  } catch (error) {
    console.log(error);
    throw error; // 必须抛出错误,让React Query捕获到失败状态
  }
};

const { data: listDocs, status } = useQuery({
  queryKey: ["firestoreListDocuments", loc], // 加入loc作为依赖,避免不同loc的数据缓存冲突
  queryFn: fetchListDocs,
});

关键修改点

  • 用snapshot.docs.map()替代forEach,生成包含所有异步操作的Promise数组。
  • 用Promise.all(pricePromises)等待所有价格请求完成后,再从Map中提取结果返回。
  • 修正queryKey,加入loc作为依赖,确保不同位置的数据能正确缓存和刷新。
  • 在catch块中抛出错误,让React Query能正确识别请求失败状态。

额外说明

如果需要同时返回Firebase文档数据和对应价格,可以调整代码返回对象数组:

// 修正后的返回逻辑示例
return snapshot.docs.map(doc => {
  const docData = doc.data();
  return {
    ...docData,
    currentPrice: tickerPriceMap.get(docData.stockTicker)
  };
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:50:24