Angular подписка внутри подписки

В компоненте есть вызов сервиса, после ответа которого надо проверив внутреннее состояние или вызвать другой метод или показать модальное окно и потом вызвать этот метод. Из за этого получается подписка внутри подписки. Подскажите, пожалуйста, как убрать вторую подписку. Условный код: пример кода на stackblitz


Ответы (1 шт):

Автор решения: Neverm1ndo

Можно использовать операторы filter и switchMap.

  • filter для проверки на значение source и фильтрации потока
  • switchMap для отписки от предыдущего потока и подписки на следующий.

Должно получиться что-то подобное:

  onExampleMethod(): void {
    this.someService.getData()
                    .pipe(
                      takeUntil(this.destroy),
                      filter(() => {
                        if (this.source === 'aa') {
                          this.create();
                          return false;
                        }
                        return true;
                      }),
                      switchMap(() => this._openDialog())
                    )
                    .subscribe((dialogData: any) => {
                      this.food = dialogData;
                      this.create();
                    });
  }
  private _openDialog(): Observable<any> {
    return this.dialog.open(DialogExampleComponent, {
      width: '250px',
    }).afterClosed();
  }

Но т.к у вас условие this.source === 'aa' никак не зависит от данных, получнных из someService.getData, то лучше даже не подписываться, а сразу выполнять метод create и завершать выполнение метода onExampleMethod

  onExampleMethod() {
    if (this.source === 'aa') return this.create(); // условие никак не зависит от потока getData
    this.someService.getData()
                    .pipe(
                      takeUntil(this.destroy),
                      switchMap(() => this._openDialog())
                    )
                    .subscribe((dialogData: any) => {
                      this.food = dialogData;
                      this.create();
                    });
  }
  private _openDialog(): Observable<any> {
    return this.dialog.open(DialogExampleComponent, {
      width: '250px',
    }).afterClosed();
  }
→ Ссылка