Как отфильтровать Observable, представляющее собой массив, с помощью функции, которая возвращает Observable с логическим значением - PullRequest
0 голосов
/ 27 февраля 2019

Скажем, у меня есть наблюдаемая с именем selectedUsers$, которая возвращает наблюдаемую матрицу в следующем формате.

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

Я хочу отфильтровать этот массив на основе того, является ли пользователь администратором или нет для модуля, и собирать только те, которые не являются администраторами.Чтобы узнать, является ли пользователь администратором модуля, необходимо выполнить вызов другой функции, которая принимает значения moduleName и userId и возвращает значение true или false в качестве наблюдаемого.

Подпись для функции:

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

Я хочу создать функцию

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

Это то, что я придумал.Это неправильно, но я написал это, чтобы вы поняли лучше.Проблема в том, что фильтр является методом массива, и функция внутри него возвращает Observable логического типа.

Есть какие-нибудь идеи о том, как отфильтровать Observable, который возвращает массив, и переданная функция в фильтре возвращает Observable, равное true или false, на основе значения объекта в массиве?

Спасибо

1 Ответ

0 голосов
/ 27 февраля 2019

Похоже, вы используете RxJS 5.0 в своих фрагментах, но вот возможное решение с RxJS 6.0.

Вы должны быть в состоянии модифицировать это.

Аспекты, на которые следует обратить внимание:

  • switchMap() принимает самую последнюю возвращенную коллекцию пользователей
  • Необходимость вызова isUserAdministratorForModule для каждого пользователя означает, что вы в конечном итоге наберете Observable<boolean>[]
  • Использование of(user) с forkJoin() связывает каждого пользователя с его isUserAdministratorForModule результатом
  • Затем merge() собирает каждое наблюдаемое пользователем значение результата обратно в один поток
  • Наконец, комбинация 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...