Firestore如何获取文档内存储的DocumentReference指向的数据
问题分析
当前代码存在3个核心问题:
post.userReference本身就是Firestore返回的标准DocumentReference类型,不需要手动new DocumentReference实例化,你的写法反而会破坏原本的引用结构forEach中传入异步函数不会等待异步操作完成,执行resolve(posts)的时候,所有用户数据的查询请求都还没返回结果- 把实时监听的
onSnapshot包裹在Promise里是不合理的,onSnapshot会在数据每次变更时触发回调,但Promise只会resolve一次,如果你只需要拉取一次时间线数据,直接用getDocs更合适
解决方案
场景1:单次拉取时间线数据(适配Promise返回需求)
import {COLLECTIONS, db} from '@/firebase' import { collection, query, orderBy, getDocs, getDoc, } from 'firebase/firestore' export default async function timeline() { const colRef = query(collection(db, COLLECTIONS.posts), orderBy('created', 'desc')) const querySnapshot = await getDocs(colRef) // 用Promise.all等待所有用户数据查询完成 const posts = await Promise.all(querySnapshot.docs.map(async (snapDoc) => { const post = snapDoc.data() const {created, userReference} = post // 直接调用getDoc获取引用指向的用户文档数据 const userSnap = await getDoc(userReference) return { ...post, id: snapDoc.id, created: +created.toDate(), user: userSnap.data() // 取出的用户数据存在user字段中 } })) return posts }
场景2:需要实时监听时间线变更
不要用Promise包裹逻辑,改成回调形式实现:
import {COLLECTIONS, db} from '@/firebase' import { collection, query, orderBy, onSnapshot, getDoc, } from 'firebase/firestore' export default function timeline(onUpdate, onError) { const colRef = query(collection(db, COLLECTIONS.posts), orderBy('created', 'desc')) // 返回取消监听的函数,方便组件卸载时调用避免内存泄漏 return onSnapshot(colRef, async (querySnapshot) => { const posts = await Promise.all(querySnapshot.docs.map(async (snapDoc) => { const post = snapDoc.data() const {created, userReference} = post const userSnap = await getDoc(userReference) return { ...post, id: snapDoc.id, created: +created.toDate(), user: userSnap.data() } })) onUpdate(posts) }, onError) } // 调用示例 // const unsubscribe = timeline( // (posts) => console.log('最新时间线数据:', posts), // (err) => console.error('查询失败:', err) // ) // 组件卸载时执行 unsubscribe() 取消监听
内容的提问来源于stack exchange,提问作者Jesus Marcano
相关产品推荐
相关产品推荐

