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
相关产品推荐
相关产品推荐

