2016-11-10 2 views
2

私はAngularFire2を使用しようとしています。私はクエリを実行しており、以下はすべて正常に動作します。複数のネストされたfirebaseオブザーバブルを折りたたみ/チェーンします

私は1つに観測のすべて/ほとんどを組み合わせたい:

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

... 
+0

私は質問者の元のコードにあなたの変更を分離するためにあなたの質問を編集しました。答えを受け入れた後、答えが正しく質問に答えられなくなるように質問を修正しました。 Q/Aは誰にも分かりませんので、避けるべきだと思います。 – cartant

+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; 
    }); 
} 
関連する問題