I have a class Store which is as follows:
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
}
And my 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 }))))
)
}
}
The InstallationStore is being subscribed to the get observable two times in two different components which trigger the getActiveInstallationUseCase twice. getActiveInstallationUseCase.execute() returns a Promise. What I would like to do is that no matter how many subscribers it has, it only runs the use case whenever the user logs in.
I have tried the share() operator with no success as follows:
get(): Observable<State> {
return this.loginStore
.get()
.pipe(
switchMap(() => from(this.getActiveInstallationUseCase.execute()).pipe(map(x => ({ activeInstallation: x })))),
share()
)
}
And
get(): Observable<State> {
return this.loginStore
.get()
.pipe(
switchMap(() => from(this.getActiveInstallationUseCase.execute()).pipe(map(x => ({ activeInstallation: x }))), share()),
)
}
But it still runs twice. I have checked that this.loginStore.get() emits an event only once and have tried to replace share with shareReplay but with no luck.
I have replicated the issue here. It's calling the promise 4 times, while I would like it to be executed only twice. Adding the share() operator makes it work, however in my code is not, why?