简体   繁体   English

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

[英]How to filter an Observable that is an array by a function that returns an Observable of boolean

Say I have an observable called selectedUsers$ that returns an Observable that is an array in the following format.假设我有一个名为selectedUsers$的 observable,它返回一个 Observable,它是以下格式的数组。

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

I want to filter this array based on if the user is an administrator or not for a module and only collect the ones that are not administrators.我想根据用户是否是模块的管理员来过滤这个数组,并且只收集不是管理员的那些。 To get if the user is an administrator for a module, a call has to be made to another function that takes the moduleName and userId value and returns true or false as an Observable.要获取用户是否是模块的管理员,必须调用另一个函数,该函数采用moduleNameuserId值并返回 true 或 false 作为 Observable。

The signature for the function is该函数的签名是

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

The function I want to create is我要创建的功能是

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

That's what I have come up with.这就是我想出的。 It is wrong but I have written it so you get a better idea.这是错误的,但我已经写了它,所以你会有一个更好的主意。 The problem is the filter is an array method and the function inside of it returns an Observable of boolean.问题是过滤器是一个数组方法,它里面的函数返回一个布尔值的 Observable。

Any ideas on how to filter an Observable that returns an array and the passed in function in the filter returns an Observable of true or false based on a value on an object in the array?关于如何过滤返回数组的 Observable 以及过滤器中传入的函数根据数组中对象的值返回真或假的 Observable 的任何想法?

Thanks谢谢

Looks like you're using RxJS 5.0 in your snippets, but here's a possible solution with RxJS 6.0.看起来您在代码片段中使用了 RxJS 5.0,但这里有一个使用 RxJS 6.0 的可能解决方案。

You should be able to retrofit this.您应该能够对此进行改造。

Aspects to point out:需要指出的方面:

  • switchMap() accepts the most recent collection of users returned switchMap()接受最近返回的用户集合
  • Having to invoke isUserAdministratorForModule for each user means you end up with Observable<boolean>[] isUserAdministratorForModule为每个用户调用isUserAdministratorForModule意味着你最终会得到Observable<boolean>[]
  • Using of(user) with forkJoin() associates each user with their isUserAdministratorForModule result使用of(user)forkJoin()每个用户与其isUserAdministratorForModule结果相关联
  • The merge() then collects each user-result value observable back into a single stream然后merge()将每个可观察到的用户结果值收集回单个流
  • Finally, the combination of filter() and map() weeds out the users of interest最后, 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM