如何使用flatMap嵌套对象?

时间:2017-01-24 14:04:14

标签: angular typescript

我想查询不同的其他资源,并希望将结果合并到一个对象中。它是一个用户对象,每个用户都应该包含一个角色。我已经阅读过我可以使用flatMap来做到这一点,但我不能让它工作:

public getUsers(): Observable<User[]> {
  var users: Observable<User[]>  = this.someService.getUsers('[A_URL]') // returns Observable<User[]>
  .flatMap(res=> {
      // for every user call resource 'role' and add it to user object one by one ...
      // return this.someService.getRoleByUser('[A_URL_WITH_USERID]')
    }.map(res=>{
      //add role to user object
      // user.role = r;
    });
  );
  return users;
}

我很抱歉伪代码,但我真的不懂语法。问题是,第二次资源调用需要第一次调用时每个用户的id。

1 个答案:

答案 0 :(得分:2)

以下是您可以这样做的方法:

// This obs emits a SINGLE array of all users.
// Analog to what your `.getUsers()` method would return
const usersArray = Rx.Observable.of([
  { id: 1, name: 'user1' },
  { id: 2, name: 'user2' },
  { id: 3, name: 'user3' }
]);

// Obtain the role(s) for a given user.
const userRoles = function(userId) {
  return Rx.Observable.of(`Role for user ${userId}`);
}

const obs = usersArray
              // Flatten the array.
              // Now each user is emitted as an individual value.
              .mergeMap(val => val)
              // Fetch user roles
              .mergeMap(user => {
                return userRoles(user.id).map(role => {
                  // Put together user + role
                  user.role = role;
                  // DO NOT FORGET to return below
                  return user;
                });
              })

              // At this point, you have individual users with a `user.role` property
              // being emitted in the stream.

              // Unflatten the array if desired (to obtain a SINGLE array of ALL users)
              .reduce((acc, curr) => acc.concat(curr), []);

// Final subscribe
obs.subscribe(val => console.log(val));

JS BIN演示此代码:http://jsbin.com/vucuga/4/edit?js,console

注意:

  • flatMap()mergeMap()的别名。在RxJS 5(Angular使用的)中,我相信mergeMap()是“官方”运营商。
  • 如果您需要保留用户的订单,请使用concatMap()代替mergeMap()