Как объединить несколько наблюдаемых значений с помощью forkjoin, чтобы получить одно наблюдаемое значение

Пытаюсь получить Observable<boolean> для моего Стража, объединив два значения Observable<boolean> через forkJoin.

Я пробовал этот подход раньше:

    isAllowedToEditSession(sessionId: number): Observable<boolean> {
        const isAllowed$: BehaviorSubject<boolean> = new BehaviorSubject(false);
        const hostName = this.authService.getMyDisplayName();
        this.sessionProxyService.getSessionById(sessionId).subscribe(session => {
          if (session.hostName === hostName) {
            isAllowed$.next(true);
          }
        });
        this.userService.isUserAdmin().subscribe(isAdmin => 
   isAllowed$.next(isAdmin));
        return isAllowed$.asObservable();
      }

Это сработало, но только потому, что this.userService.isUserAdmin() — это BehaviorSubject и у него уже было сохранено значение, поэтому он выполнялся синхронно.

Это мой текущий подход, который не дает мне того результата, на который я надеялся.

isAllowedToEditSession(sessionId: number): Observable<boolean> {
    const hostName = this.authService.getMyDisplayName();
    const isAllowed$ = forkJoin(
      this.sessionProxyService.getSessionById(sessionId),
      this.userService.isUserAdmin()
    ).pipe(
      map(([session, isAdmin]) => {
        const isHost = session.hostName === hostName;
        console.info(isHost || isAdmin);
        return isHost || isAdmin;
      })
    );
    return isAllowed$;
  }

isAllowed$ распознается как Observable<boolean>, но неправильно выдает эти значения.

ОБНОВИТЬ

Это работает (см. принятый ответ для объяснения):

isAllowedToEditSession(sessionId: number): Observable<boolean> {
    const hostName = this.authService.getMyDisplayName();
    const isAllowed$ = forkJoin(
      this.sessionProxyService.getSessionById(sessionId), //pipe(take(1)) not needed here
      this.userService.isUserAdmin().pipe(take(1))
    ).pipe(
      map(([session, isAdmin]) => {
        const isHost = session.hostName === hostName;
        return isHost || isAdmin;
      })
    );
    return isAllowed$;
  }

Как это не работает? Вы получаете сообщение об ошибке?

Reactgular 22.07.2019 19:33

Извините, я должен был указать ожидаемое поведение. Это не работает, потому что не выдает true, хотя либо isHost, либо isAdmin должны возвращать true в моем случае использования. Но принятый ответ был решением моей проблемы.

BingeCode 23.07.2019 08:47
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
2
2
506
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

forkJoin требует, чтобы все исходные Observable выдавали хотя бы одно значение, а затем завершались. И это проблема у вас есть. Вы используете BehaviorSubject внизу, что не завершается, пока вы не вызовете .complete() на нем.

Вы должны сделать, например, это:

if (session.hostName === hostName) {
  isAllowed$.next(true);
  isAllowed$.complete();
}

Так что это зависит от того, как реализованы getSessionById() и isUserAdmin(). Вы также можете передать их обоих с помощью take(1), прежде чем передавать их в forkJoin.

Спасибо! Это была моя проблема. Однако у меня есть вопрос: автоматически ли завершаются http-вызовы? Потому что мне не нужно было .pipe(take(1)) на this.sessionProxyService.getSessionById(sessionId), что является вызовом. Я обновил свой пост с окончательным решением.

BingeCode 23.07.2019 08:52

Да, если вы имеете в виду HttpClient в Angular, они выполняются автоматически.

martin 23.07.2019 09:17

Другие вопросы по теме