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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 07:57:00