2017-02-23 70 views
1
const placeId = this.getPlaceId(); 
     this.af.database.list(`placeUsers/${placeId}`).subscribe((userKeys) => { 
      for (let index = 0; index < userKeys.length; index++) { 
       let userKey = userKeys[index]; 

       this.af.database.list(`userDevices/${userKey.$key}`).subscribe((deviceKeys) => { 

        for (let index = 0; index < deviceKeys.length; index++) { 
         let deviceKey = deviceKeys[index]; 

         this.af.database.object(`devices/${deviceKey.$key}`).subscribe((device) => { 

          console.log(device); 
          // Device received.  

         }); 
        } 
       }); 
      } 
     }); 

我目前正在嘗試向所有用戶關注地點發送通知。目前的流程是這樣的:合併多個FirebaseListObservables

  • 獲取屬於一個地方的用戶(placeUsers節點)
  • 獲取屬於用戶deviceKeys(userDevices節點)
  • 從deviceKeys獲取設備(設備節點)

我想知道是否有一種方法可以將所有這些調用合併爲一個可觀察調用。

我目前的問題是,我無法知道所有這些請求何時完成。我研究過RxJs,它可以讓我把所有這些可觀察結果結合起來。但我還沒有找到一個很好的解決方案,如何與四個節點。

回答

1

您可以使用concatMapforkJoin組成發射設備的可觀測量。這個組成的可觀察到的將發射器件的一個陣列和將然後完成(作爲first運算符用於採取只有第一發射列表或對象):

import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/concatMap'; 
import 'rxjs/add/operator/first'; 
import 'rxjs/add/operator/forkJoin'; 

this.af.database 
    .list(`placeUsers/${placeId}`) 
    .first() 
    .concatMap(userKeys => { 
    let observables = userKeys.map(userKey => this.af.database 
     .list(`userDevices/${userKey.$key}`) 
     .first() 
    ); 
    return observables.length ? 
     Observable.forkJoin(...observables, (...lists) => [].concat(...lists)) : 
     Observable.of([]) 
    }) 
    .concatMap(deviceKeys => { 
    let observables = deviceKeys.map(deviceKeys => this.af.database 
     .object(`devices/${deviceKey.$key}`) 
     .first() 
    ); 
    return observables.length ? 
     Observable.forkJoin(...observables) : 
     Observable.of([]) 
    }) 
    .subscribe(devices => console.log(devices)); 

如果要可觀察到的該未完成併發射

import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/combineLatest'; 
import 'rxjs/add/operator/switchMap'; 

this.af.database 
    .list(`placeUsers/${placeId}`) 
    .switchMap(userKeys => { 
    let observables = userKeys.map(userKey => this.af.database 
     .list(`userDevices/${userKey.$key}`) 
    ); 
    return observables.length ? 
     Observable.combineLatest(...observables, (...lists) => [].concat(...lists)) : 
     Observable.of([]) 
    }) 
    .switchMap(deviceKeys => { 
    let observables = deviceKeys.map(deviceKeys => this.af.database 
     .object(`devices/${deviceKey.$key}`) 
    ); 
    return observables.length ? 
     Observable.combineLatest(...observables) : 
     Observable.of([]) 
    }) 
    .subscribe(devices => console.log(devices)); 
+1

什麼用途使用傳播經營者可觀測陣列(:換一個地方,只要一個地方的用戶或他們的設備的變化,使用switchMap代替concatMapcombineLatest代替forkJoin並刪除first運營商的設備'... observab如果'forkJoin'&'combineLatest'每個都可以有一個數組參數,那麼在這裏服務? – patrickmcd

+0

@patrick沒有技術上的原因。只是儘可能簡單地保留一個已經很長的答案。文檔(就是這樣)沒有(或者沒有)很清楚你可以傳遞一個數組,所以我不想解釋這個。另外,我似乎記得(至少在測試期間)有一些運算符不接受數組參數,但它們都使用擴展語法。 – cartant

+1

@patrick我可以提供另一個支持傳播語法的理由,因爲它只是咬了我。有些方法(比如'Observable.concat')會將一個數組視爲一個[ObservableInput](http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObservableInputDoc.html) - 並將連接數組的元素 - 所以我認爲如果使用擴展語法,方法之間的事情會更加一致。 – cartant