展平/链接多个嵌套的firebase Observables

时间:2016-11-10 20:08:06

标签: firebase firebase-realtime-database observable rxjs5 angularfire2

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

我想将所有/大多数观察者合并为一个:

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;
        })
  }

我想知道我是否可以加入所有的observable并使用单个订阅函数获取输出。

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

此外,如何扩展到包含每轮比赛?

我对上述代码的扩展名为:

...

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; })

...

1 个答案:

答案 0 :(得分:3)

您可以使用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;
    });
}

每当任何一个观察者发出时,最新的值将被重新组合,并且会发出新的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;
    });
}