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

RxJS: ES6 Array every() equivalent to check each item in an array of Observable booleans

我有一个 'roles' 数组,需要检查用户是否具有这些角色中的每一个。检查这个的函数,return是一个 Observable:

let roles: string[] = ['role1', 'role2']

public userHasRole(role: string): Observable<boolean> {<already implemented>}

我需要 return 一个 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)),
  );
}

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

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

添加导入语句

import { of } from 'rxjs';

试试这个:

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 function first creates an observable that emits the roles in sequence. Then mergeMap creates a flattened stream of boolean results from calling currentUserHasRole for each role emitted. Finally reduce 将所有布尔值合并为一个布尔值,该布尔值仅在所有输入布尔值都为真时才为真,类似于 Array.reduce 的工作方式。

reduce 这里类似于 forkJoin:它 returns 一个可观察对象,一旦输入可观察对象完成,它就会发出一次合并值。返回的可观察对象将自行完成。