Angular2 RxJS流为父集合的每个子节点调用HTTP

时间:2016-07-05 17:38:59

标签: angular reactive-programming rxjs

我有一个调用http的组件来获取对象(用户)的集合。对于每个用户,我需要进行另一个单独的http调用以获取用户的其他详细信息。如何使用RxJS和observables执行此操作?在这个插件中显示的行为,我们获取github用户列表,然后尝试检索他们的每个关注者以获得关注者数。

订阅代码位于user-grid.component.ts。

http://plnkr.co/edit/Xuu5jqeKVmbY5qwHLJJt

ngOnInit(){
    this.users$ = this._githubUserService.getUsers()
        .map((res) => res.json())
        .flatMap((users) => Observable.from(users))
        .flatMap((e) => {
          return this._githubUserService.getFollowers(e.followers_url)
          .map((followers)=> followers.json())
         }, (e, res) => e.followers = res)     
}

2 个答案:

答案 0 :(得分:1)

我对异步管道并不十分熟悉,但似乎问题是*ngForObservable中的每个新值视为列表的补液。传递给flatMap的第二个函数是返回从跟随者调用返回的数组(顺便说一下,为什么它似乎也闪烁,因为每次新请求解析时它都会重建列表)。 / p>

我认为如果你将toArray运算符附加到结尾,等待所有值都返回。

此外,由于您要将followers解析为数组,因此不需要在嵌套的h4上使用异步管道。

见这里:

http://plnkr.co/edit/X2OjHGiPpmml2cmLD1tm?p=preview

有趣的一点:

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/toArray';


ngOnInit(){
    this.users$ = this._githubUserService.getUsers()
        .map((res) => res.json())
        .flatMap(users => users)
        .flatMap(
          (e) => this._githubUserService.getFollowers(e.followers_url), 
          (e, res) => Object.assign(e, {followers: res.json()}))
        .toArray();
}

// in user-grid.component.html
<md-list>
  <h1 md-header>GitHub Users</h1>
  <md-list-item *ngFor="let user of users$ | async">
    <a href="https://github.com/{{user.login}}" target="_new">
      <img md-list-avatar [src]="user.avatar_url">
    </a>
    <h4>{{user.login}} (followers: {{user.followers.length}})</h4>
  </md-list-item>
</md-list>

答案 1 :(得分:0)

我无法打开你的plnkr(它让我返回403 - 禁止),但我认为如果你想建立一个这样的结构:

[{ userId: 1, followersQtt : 25 }, { userId: 2, followersQtt : 18 }, ... ]

你可以这样做:

//get the users' json as an Array
let usersJsonArray = this._githubUserService.getUsers().map((res) => res.json()); 

this.users$ = Observable.from(usersJsonArray) //we have to convert the Array to an Observable               
                .flatMap((user) => {

                    //get the followers' json
                    let followersJsonArray = this._githubUserService.getFollowers(user.followers_url).map((res) => res.json());

                    return Observable.from(followersJsonArray) //again, we have to convert the Array to an Observable                               
                                .map(() => 1) //map each follower to the number 1
                                .reduce((x,y) => x+y) //sums up all the followers (that were mapped to the number '1')
                                .map((followersQtt) => { userId : user.id, followersQtt : followersQtt }) //return an object with the informations (I don't know if the user's id is really in the property user.id)    

                });