如何通过返回布尔值的Observable的函数过滤作为数组的Observable

时间:2019-02-27 01:16:36

标签: javascript angular rxjs reactive-programming

说我有一个名为selectedUsers$的可观察对象,它以以下格式返回一个数组的可观察对象。

[
 {
   'userId': 'someId',
   'other': 'properties',
   'that': 'dont',
   'matter': '.',
 },
 {
   'userId': 'anotherId',
   'other': 'properties',
   'that': 'dont',
   'matter': '.',
 },
 {
   'userId': 'yetAnotherId',
   'other': 'properties',
   'that': 'dont',
   'matter': '.',
 },
];  

我想根据用户是否是某个模块的管理员来过滤该数组,而仅收集不是管理员的模块。要确定用户是模块的管理员,必须调用另一个函数,该函数采用moduleNameuserId值并返回true或false作为Observable。

该功能的签名为

isUserAdministratorForModule$(moduleName: string, userId: string): Observable<boolean>  

我要创建的函数是

getNonAdministratorUsersForModule$(moduleName: string): Observable<IUser[]> {
   return this.selectedUsers$.map(selectedUsers => selectedUsers.map(user => 
          user.id)
         .filter(userId => !this.userService.isUserAdministratorForModule$(moduleName, userId))
}  

这就是我想出的。是错误的,但是我已经写了,所以您有更好的主意。问题是过滤器是一个数组方法,其内部的函数返回一个Observable布尔值。

关于如何过滤返回数组的Observable的任何想法,以及在过滤器中传递的函数根据数组中对象的值返回true或false的Observable的任何想法?

谢谢

1 个答案:

答案 0 :(得分:2)

您似乎在代码段中使用了RxJS 5.0,但这是使用RxJS 6.0的可能解决方案。

您应该能够对此进行改造。

要指出的方面:

  • switchMap()接受返回的用户的最新集合
  • 必须为每个用户调用isUserAdministratorForModule意味着您最终会遇到Observable<boolean>[]
  • of(user)forkJoin()一起使用会将每个用户与其isUserAdministratorForModule的结果相关联
  • merge()然后将每个可观察到的用户结果值收集回到单个流中
  • 最后,filter()map()的结合会淘汰感兴趣的用户

const { forkJoin, merge, of } = rxjs;
const { filter, map, switchMap } = rxjs.operators;

const selectedUsers = [
  {
    'userId': 'someId',
    'other': 'properties',
    'that': 'dont',
    'matter': '.',
  },
  {
    'userId': 'anotherId',
    'other': 'properties',
    'that': 'dont',
    'matter': '.',
  },
  {
    'userId': 'yetAnotherId',
    'other': 'properties',
    'that': 'dont',
    'matter': '.',
  },
];

function isUserAdministratorForModule(moduleName, userId) {
  return of(userId === 'someId');
}

function getNonAdministratorUsersForModule(moduleName) {
  return of(selectedUsers).pipe(
    switchMap(users =>
      merge(...users.map(user =>
        forkJoin(
          of(user),
          isUserAdministratorForModule(moduleName, user.userId))
        ),
      ),
    ),
    filter(([user, isAdmin]) => !isAdmin),
    map(([user, isAdmin]) => user),
  );
}

getNonAdministratorUsersForModule().subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>