如何使用flatMap嵌套对象



我想查询不同的休息资源,并希望将结果合并到一个对象中。它是一个用户对象,每个用户都应该包含一个角色。我已经阅读了我可以使用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。

这是

你可以做到的:

// 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()