我有一个"角色"数组,需要检查用户是否拥有这些角色中的每一个。检查此项的函数返回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:它返回一个可观察对象,该可观察对象在输入可观察对象完成后立即发出一次组合值。然后,返回的可观测对象将自身完成。
根据方法签名,您只需要将一个字符串作为参数,因此您可以简单地使用findIndex
和of
运算符将其转换为Observable
public userHasRole(role:string): Observable<boolean>{
roles.findIndex(i=>i===role)!==-1 ? of(true) : of(false)
}
添加导入语句
import { of } from 'rxjs';