Rx JS: ES6 массив каждого () эквивалентного для проверки каждого элемента в массиве наблюдаемых логических значений - PullRequest
0 голосов
/ 04 марта 2020

У меня есть массив «ролей», и мне нужно проверить, есть ли у пользователя каждая из этих ролей. Функция для проверки этого возвращает Observable:

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

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

Мне нужно вернуть Observable<boolean> или Promise<boolean>, который указывает, принадлежит ли пользователь каждой роли.

I можно решить это с помощью обещаний:

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

но я предполагаю, что есть более элегантное решение с Rx JS? Я использую RX js 6,5.

Ответы [ 3 ]

1 голос
/ 04 марта 2020

Попробуйте это:

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, только если все входные логические значения были истинными, аналогично тому, как работает Array.reduce.

reduce здесь аналогично forkJoin: он возвращает наблюдаемую единицу, которая излучает один раз с объединенным значением, как только завершается входная наблюдаемая. Возвращенная наблюдаемая затем сама завершится.

1 голос
/ 04 марта 2020

Для Rx JS, попробуйте:

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)),
  );
}
0 голосов
/ 04 марта 2020

Согласно сигнатуре вашего метода, вы берете только одну строку в качестве аргумента, поэтому вы можете просто использовать операторы findIndex и of, чтобы преобразовать ее в Observable

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

и добавить заявление на импорт

import { of } from 'rxjs';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...