2017-06-20 36 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'。代码固定。 –