如何运行嵌套Firestore查询?解决doc不是函数的类型错误
问题解决:Firestore查询优惠并判断用户使用状态
错误原因分析
- 变量名冲突:你在
snapshot.forEach((doc) => {})里把参数命名为doc,这和Firebase提供的doc()函数重名了,导致回调内部调用的doc()其实是快照对象,不是创建文档引用的函数,所以抛出「doc is not a function」的错误。 - 异步操作未正确处理:
getDoc()是异步函数,直接调用会返回Promise对象,无法直接调用exists()方法,必须用await等待它完成。
正确实现代码
import { doc, collection, query, where, getDocs, getDoc } from "firebase/firestore"; export const getOffers = async (id, uid) => { const offersRef = collection(FIREBASE_FIRESTORE, "venues", id, "offers"); const q = query(offersRef, where("active", "==", true)); const snapshot = await getDocs(q); // 用map生成包含异步操作的Promise数组,再用Promise.all等待全部完成 const offersData = await Promise.all( snapshot.docs.map(async (docSnapshot) => { // 这里用docSnapshot作为参数名,避免和doc函数冲突 const redemptionRef = doc(FIREBASE_FIRESTORE, "users", uid, "redemptions", docSnapshot.id); const redemptionSnapshot = await getDoc(redemptionRef); return { id: docSnapshot.id, exists: redemptionSnapshot.exists(), ...docSnapshot.data(), }; }) ); return offersData; };
关键修改点
- 将forEach回调的参数名从
doc改为docSnapshot,避免覆盖Firebase的doc()函数。 - 使用
map替代forEach生成Promise数组,配合Promise.all批量处理异步的getDoc请求,确保所有优惠的使用状态都查询完成后再返回结果。 - 在
getDoc前添加await,等待异步操作完成后再获取快照的exists()状态。
内容的提问来源于stack exchange,提问作者David Henry
相关产品推荐
相关产品推荐

