RxJS:ES6 Array every()等效于检查Observable布尔值数组中的每个项



我有一个"角色"数组,需要检查用户是否拥有这些角色中的每一个。检查此项的函数返回Observable:

let roles: string[] = ['role1', 'role2']
public userHasRole(role: string): Observable<boolean> {<already implemented>}

我需要返回一个Observable<boolean>Promise<boolean>,指示用户是否拥有每个角色。

我可以用Promises:解决这个问题

let promises: Promise<boolean>[] = roles.map(r => this.auth.currentUserHasRole(r).toPromise());
return Promise.all(promises).then(results => results.every(x => x));

但我认为RxJS有一个更优雅的解决方案?我使用的是rxjs 6.5。

对于RxJS方式,请尝试:

import { combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
public userHasRoles(roles: string[]): Observable<boolean> {
 return combineLatest(
    // spread the array of observables as a comma list
    ...roles.map(role => this.auth.currentUserHasRole(role)),
  ).pipe(
    map(results => results.every(result => result)),
  );
}

试试这个:

public userHasRoles(roles: string[]): Observable<boolean> {
    return from(roles).pipe(
        mergeMap((role) => this.auth.currentUserHasRole(role)),
        reduce((hasPrevRoles, hasRole) => hasPrevRoles && hasRole),
    );
}

使用以下导入:

import { from } from 'rxjs';
import { mergeMap, reduce } from 'rxjs/operators';

from函数首先创建一个按顺序发射角色的可观察对象。然后,mergeMap通过为每个发出的角色调用currentUserHasRole来创建布尔结果的扁平流。最后,reduce将所有布尔值组合为一个布尔值,只有当所有输入布尔值都为true时,该布尔值才为true,类似于Array.reduce的工作方式。

这里的reduce类似于forkJoin:它返回一个可观察对象,该可观察对象在输入可观察对象完成后立即发出一次组合值。然后,返回的可观测对象将自身完成。

根据方法签名,您只需要将一个字符串作为参数,因此您可以简单地使用findIndexof运算符将其转换为Observable

public userHasRole(role:string): Observable<boolean>{
     roles.findIndex(i=>i===role)!==-1 ? of(true) : of(false)
}

添加导入语句

import { of } from 'rxjs';

最新更新