2017-06-20 69 views
0

我一直在努力從我的http請求序列中獲得正確的效果。我必須做一個返回一個網站對象數組的初始請求。然後,我必須使用站點對象中找到的兩個id再創建兩個http請求,以獲取關聯的站點組織名稱和團隊名稱,並將它們添加到每個站點對象。所以,我的步驟是:網站更好的實現可觀察序列的方法

  1. 獲取列表
  2. 使用現場組織ID來獲得相關的組織,並添加名字到站點對象。
  3. 使用網站團隊ID獲取相關團隊並將團隊名稱添加到網站對象。

我的代碼如下:

private getSites() { 
    this.spinner.show(); 
    this.sitesService.getSitesByUserId(this.userId) 
    .subscribe(
     _data => { 
     _data.map(site => { 
      this.orgService.getOrganization(site['OrganizationId']) 
      .map(org => { 
       site['orgName'] = org['org']['name']; 
       return org; 
      }) 
      .flatMap(() => this.teamsService.getTeam(site['TeamId'])) 
      .map(team => { 
       site['teamName'] = team['team']['name']; 
       return team; 
      }) 
      .subscribe(
       _d => { 
       this.sites.push(site); 
       } 
      ); 
     }); 
     }, 
     _error => {}, 
    () => { 
     this.spinner.hide(); 
     this.loading = false; 
     } 
    ); 
} 

在我的HTML我綁定數據:

<div *ngFor="let site of (sites | filterlist: value : 'name')"> 
    <card-directory-item (click)="siteSelected(site)"> 
    <i class="material-icons item-icon">location_city</i> 
    <h2 class="item-name">{{ site.name }}</h2> 
    <div class="item-field-1">{{ site.city }} {{ site.state }} </div> 
    <div class="item-static-field flex-column"> 
     <div>{{ site.teamName }}</div> 
     <div>{{ site.orgName }}</div> 
    </div> 
    </card-directory-item> 
</div> 

問題是微調器完成所有步驟之前被刪除每個清單項目都按照完成的順序彈出。我知道這是爲什麼發生。我只是無法弄清楚如何鏈接可觀察的流來完成一切,然後才能移除微調器並顯示數據。

任何協助將是偉大的。謝謝。

回答

1

問題是你subscribegetSitesByUserId(this.userId)返回的可觀察「太早」。

這裏你的代碼看起來有點像這樣

this.sitesService.getSitesByUserId(this.userId) 
    .subscribe(
    otherAsyncOp, 
    errorCallback, 
    completeCallback 
) 

的事情是,在onCompleteCallback被稱爲每當通過getSitesByUserId返回的觀察到完成這是你對他人的HTTP請求已完成之前。

如果要依次調用所有的網址,你將不得不使用mergeMap(或flatMap這是一個別名)這樣

this.sitesService.getSitesByUserId(this.userId) 
    .mergeMap(sites => Rx.Observable.from(sites)) // create an observable per site 
    .mergeMap(site => this.sitesService.getOrga(site.id) 
         .map(orga => Object.assign({}, site, { orgName: orga.org.name })) 
    .mergeMap(site => this.sitesService.getTeam(site.teamId).map(team => Object.assign({}, site, {teamName: team.team.name}) 
    .reduce((sites, site) => sites.concat(site), []) 
    .subscribe(/* there every request should be done and you can remove your loader */) 

很抱歉,這是一個相當長的答案,但是你的問題是非常廣闊。我無法執行該代碼,所以我不能100%確定它的工作原理,但至少你明白了。

+0

謝謝。這工作非常好,我從你的解決方案中學到了很多東西。其實從雙方都學到了。 :) – Aaron

+0

太棒了,感謝您的反饋。學習是最好的感覺:)很高興我可以幫助 – atomrc

1

您可以將每個站點映射到組織請求和團隊請求的zip。 zip的第三個參數是可以用Object.assign組成最終對象的回調。

this.sitesService 
    .getSitesByUserId(this.userId) 
    .mergeMap(sites => Observable.from(sites)) 
    .mergeMap(site => { 
    return Observable.zip(
     this.orgService.getOrganization(site['OrganizationId']), 
     this.teamService.getTeam(site['TeamId']), 
     (org, team) => Object.assign(site, { 
     orgName: org['org']['name'], 
     teamName: team['team']['name'] 
     }) 
    ) 
    }) 
    .subscribe(console.log) 
+0

這是很好的代碼,但它不適用於我的情況。我相信,如果mergeMap中的網站是一個單一的網站對象,這將工作,但在我的情況下,它是一個網站對象的數組。所以當你的代碼調用this.teamService.getTeam(site ['TeamId']​​)時,id是未定義的。 – Aaron

+0

我明白了。所以你只需要另一個'mergeMap'。代碼固定。 –