Flatten/Chain 多个嵌套的 firebase Observables

Flatten/Chain multiple nested firebase Observables

我正在尝试使用 AngularFire2。我正在查询,下面一切正常。

我想将 all/most 个 observables 合并为一个:

getTournamentWithRounds(key):Observable<Tournament> {

    return this.af.database
        .object(`/tournaments/${key}`)
        .map(tourney => {

            let t = Tournament.fromJson(tourney);

            this.af.database.list('players', {
                query: {
                    orderByChild: 'tournament_key',
                    equalTo: key
                }
            })
            .map(Player.fromJsonList)
            .subscribe(ps => { t.players = ps; });

            this.af.database.list('rounds', {
                query: {
                    orderByChild: 'tournament_key',
                    equalTo: key
                }
            })
            .map(Round.fromJsonList)
            .subscribe(rs => { t.rounds= rs; })

            return t;
        })
  }

我想知道我是否可以连接所有可观察对象并使用单个订阅函数获取输出。

我想知道何时加载了所有初始数据,并在将其输出到视图之前在控制器中执行额外的计算。

此外,如何将其扩展到包括每一轮的比赛?

我对上述代码的扩展是:

...

this.af.database.list('rounds', {
    query: {
        orderByChild: 'tournament_key',
        equalTo: key
    }
})
.map(rounds => {
    return rounds.map((round) => {

        let r = Round.fromJson(round);

        this.af.database.list('matches', {
            query: {
                orderByChild: 'round_key',
                equalTo: round.$key
            }
        })
        .map(Match.fromJsonList)
        .subscribe(matches => { r.matches = matches; })

        return r;
    })
})
.subscribe(rs => { t.rounds= rs; })

...

您可以使用 combineLatest 运算符将球员和回合与锦标赛结合起来:

getTournamentWithRounds(key): Observable<Tournament> {

  return this.af.database
    .object(`/tournaments/${key}`)
    .combineLatest(
      this.af.database.list('players', {
        query: {
          orderByChild:'tournament_key',
          equalTo: key
        }
      }),
      this.af.database.list('rounds', {
        query: {
          orderByChild:'tournament_key',
          equalTo: key
        }
      })
    )
    .map(([tourney, players, rounds]) => {

      let t = Tournament.fromJson(tourney);
      t.players = Player.fromJsonList(players);
      t.rounds = Round.fromJsonList(rounds);
      return t;
    });
}

每当任何 observable 发出时,最新的值将被重新组合并发出一个新的 Tournament

将其扩展为包括每一轮的比赛稍微复杂一些,因为比赛查询需要每一轮的密钥。

发射的回合可以映射到匹配项的列表观察值数组,forkJoin 可用于连接观察值,forkJoin 选择器函数用于将匹配项与回合。 switchMap 然后用于发射弹药。

getTournamentWithRounds(key): Observable<Tournament> {

  return this.af.database
    .object(`/tournaments/${key}`)
    .combineLatest(
      this.af.database.list('players', {
        query: {
          orderByChild:'tournament_key',
          equalTo: key
        }
      }),
      this.af.database.list('rounds', {
        query: {
          orderByChild:'tournament_key',
          equalTo: key
        }
      })
      .switchMap(rounds => {
        Observable.forkJoin(
          rounds.map(round => this.af.database.list('matches', {
            query: {
              orderByChild: 'round_key',
              equalTo: round.$key
            }
          }).first()),
          (...lists) => rounds.map((round, index) => {
            let r = Round.fromJson(round);
            r.matches = Match.fromJsonList(lists[index]);
            return r;
          })
        )
      })
    )
    .map(([tourney, players, rounds]) => {

      let t = Tournament.fromJson(tourney);
      t.players = Player.fromJsonList(players);
      t.rounds = rounds;
      return t;
    });
}