Не знаете, где разместить подписку на 3 наблюдаемые, связанные с switchMap - PullRequest
1 голос
/ 24 апреля 2020
this._authService.loggedInUser$.pipe(switchMap((loggedInUser: LoggedInUser) => {
      return this._userSerialService.getUserSerial().pipe(switchMap(serial => {
          return this._usersService.getCurrentUser().pipe(switchMap(currentUser => [loggedInUser, currentUser, serial]));
        }),
      );
    })).subscribe(([loggedInUser, currentUser, serial]) => {

    });

Приведенный выше код пытается связать 3 наблюдаемых вместе и отобразить их результаты в массив с помощью switchMaps. Мне нужны значения результата для всех трех наблюдаемых в моей окончательной подписке. Однако, когда я пытаюсь подписаться, как показано выше, мне выдается ошибка компилятора, которая говорит, что `Type 'LoggedInUser' должен иметь метод Symbol.iterator, который возвращает итератор.

Если я сделаю subscribe(res => {}, то res в итоге станет только значением loggedInUser, а не всеми тремя значениями.

Что мне нужно изменить в своем коде, чтобы убедиться, что у меня есть Доступ ко всем трем значениям в моей подписке?

Ответы [ 2 ]

1 голос
/ 25 апреля 2020

Не похоже, что switchMap - это то, что вам нужно. switchMap используется для «переключения» источника, наблюдаемого под колпаком, чтобы новая наблюдаемая могла излучать в поток. Он обрабатывает отписку от предыдущего источника и подписку на новый.

В вашем случае вы можете просто использовать combineLatest. Это будет излучать массив всех 3 значений, как только все исходные наблюдаемые издадут значение, и будет продолжать излучать всякий раз, когда любое из них получит новое значение.

authUser$ = this._authService.loggedInUser$;
serial$   = this._userSerialService.getUserSerial();
user$     = this._usersService.getCurrentUser();

data$ = combineLatest([authUser$, serial$, user$]);


data$.subscribe(([loggedInUser, serial, currentUser]) => {
    ...
});

Может быть удобно отобразить значения для объекта, поэтому их легко получить в вашем шаблоне, например:

data$ = combineLatest([authUser$, serial$, user$]).pipe(
    map(([authUser, serial, user]) => ({authUser, serial, user}))
);

Это также удобно, если вы используете asyn c pipe в своем шаблоне, а не подписываетесь в ваш компонент.

<div *ngIf="data$ | async as data">
    <ul>
        <li>Current User: {{ data.user }}</li>
        <li>Logged in User: {{ data.authUser }}</li>
        <li>User Serial: {{ data.serial }}</li>
    </ul>
</div>
0 голосов
/ 24 апреля 2020

switchMap оператор принимает функцию, которая возвращает Observable, а затем подписывается на него.
Проблема здесь в том, что ваш последний switchMap получает массив вместо Observable.
. Вы можете вместо этого используйте map для преобразования данных.

this._authService.loggedInUser$.pipe(
  switchMap(loggedInUser => this._userSerialService.getUserSerial().pipe(
    switchMap(serial => this._usersService.getCurrentUser().pipe(
      map(currentUser => [loggedInUser, currentUser, serial]))
    )
  ))
).subscribe(([loggedInUser, currentUser, serial]) => {
  ...
});
...