RxJS Observable获取Firestore数据时数组有值但length为0问题求助
问题根因
- Provider的Observable创建逻辑存在时序错误:
onSnapshot是Firestore提供的异步监听回调,只有云端/本地缓存返回查询结果后才会执行。你在注册完监听器后立刻调用observer.next(map),此时回调还未触发,map还是初始化的空数组,所以下游拿到的永远是空值。 - 控制台打印能看到数组内容是浏览器的延迟求值特性导致的:打印数组时存储的是内存引用,后续异步回调往数组里push数据后,你手动展开控制台的数组条目时,浏览器读取的是数组当前的最新值,所以能看到完整内容。但在执行map操作、读取length属性的时间点,数组确实是空的,所以才会返回0、遍历不到任何条目。
- 原有逻辑用外部变量累加数组还存在额外缺陷:
onSnapshot会在数据更新时多次触发,累加逻辑会导致返回的数组出现重复数据。
修复方案
调整FirestoreLeaderboardProvider中的Observable实现,把数据推送逻辑放到onSnapshot回调内部即可:
class FirestoreLeaderboardProvider implements LeaderboardProvider { private firestore: firebase.firestore.Firestore; private leaderboardCollection: firebase.firestore.CollectionReference<firebase.firestore.DocumentData>; constructor(period: string) { this.firestore = firebase.firestore(); this.leaderboardCollection = this.firestore.collection(period + "Leaderboard"); } public observeLeaderboardSortedByScore(limit = 1, startAt?: any): Observable<Map<string, any>[]> { let query = this.leaderboardCollection.orderBy("score", "desc").limit(limit); if (startAt) query = query.startAt(startAt); return new Observable<Map<string, any>[]>((observer) => { const unsubscribe = query.onSnapshot((snapshot) => { // 每次快照返回时直接生成最新结果数组,不要用外部变量累加避免重复 const list = snapshot.docs.map((val) => new Map(Object.entries(val.data()))); // 拿到数据后再推送给下游 observer.next(list); }, (err) => { // 补充错误回调,把查询异常抛给下游处理 observer.error(err); }); return unsubscribe; }); } }
内容的提问来源于stack exchange,提问作者anonymous-dev
相关产品推荐
相关产品推荐

