Как избежать выполнения обещания внутри наблюдаемого дважды при подписке на BehaviourSubject? - PullRequest
4 голосов
/ 21 октября 2019

У меня есть класс Store, который выглядит следующим образом:

import { BehaviorSubject, Observable } from 'rxjs'

export abstract class Store<T> {
  private state: BehaviorSubject<T> = new BehaviorSubject((undefined as unknown) as T)

  get(): Observable<T> {
    return this.state.asObservable()
  }

  set(nextState: T) {
    return this.state.next(nextState)
  }

  value() {
    return this.state.getValue()
  }

  patch(params: Partial<T>) {
    this.set({ ...this.value(), ...params })
  }

  abstract create(): void
}

И мой InstallationStore:

import { Store } from '../../store/store'
import { Installation } from '../domain/installation/installation'
import { from, Observable } from 'rxjs'
import { GetActiveInstallationUseCase } from '../../../features/planning/application/get-active-installation-use-case'
import { Injectable } from '@angular/core'
import { map, switchMap } from 'rxjs/operators'
import { LoginStore } from '../../../features/login/application/login-store'

interface State {
  activeInstallation: Installation
}

@Injectable({
  providedIn: 'root'
})
export class InstallationStore extends Store<State> {
  constructor(
    private readonly getActiveInstallationUseCase: GetActiveInstallationUseCase,
    private readonly loginStore: LoginStore
  ) {
    super()
    this.create()
  }

  create(): void {
    this.set({
      activeInstallation: {
        isDefault: true,
        productionProfile: 'baz',
        incomingProfile: 'foo',
        id: 1,
        energeticRole: 'bar',
        name: ''
      }
    })
  }

  get(): Observable<State> {
    return this.loginStore
      .get()
      .pipe(
        switchMap(() => from(this.getActiveInstallationUseCase.execute()).pipe(map(x => ({ activeInstallation: x }))))
      )
  }
}

InstallationStore подписывается на get, наблюдаемый два раза в двухразличные компоненты, которые вызывают getActiveInstallationUseCase дважды . getActiveInstallationUseCase.execute() возвращает обещание. Я хотел бы, чтобы независимо от того, сколько у него подписчиков, он использует сценарий использования только тогда, когда пользователь входит в систему .

Я пробовал оператор share() безУспех выглядит следующим образом:

get(): Observable<State> {
    return this.loginStore
      .get()
      .pipe(
        switchMap(() => from(this.getActiveInstallationUseCase.execute()).pipe(map(x => ({ activeInstallation: x })))),
        share()
      )
  }

И

get(): Observable<State> {
    return this.loginStore
      .get()
      .pipe(
        switchMap(() => from(this.getActiveInstallationUseCase.execute()).pipe(map(x => ({ activeInstallation: x }))), share()),

      )
  }

Но он все равно работает дважды. Я проверил, что this.loginStore.get() генерирует событие только один раз, и попытался заменить share на shareReplay, но безуспешно.


Я повторил проблему здесь ,Он вызывает обещание 4 раза, а я бы хотел, чтобы оно было выполнено только дважды. Добавление оператора share() заставляет его работать, однако в моем коде нет, почему?

1 Ответ

1 голос
/ 21 октября 2019

Попробуйте использовать rxjs, возьмите опратор что-то вроде

 get(): Observable<State> {
    return this.loginStore
      .get()
      .pipe(
        take(1),
        switchMap(() => from(this.getActiveInstallationUseCase.execute()).pipe(map(x => ({ activeInstallation: x }))))
      )
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...