I've defined a class called Store with the following structure:
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
}
Now let's take a look at 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 problem I'm facing is that the InstallationStore is subscribed to the get observable twice in different components, causing the getActiveInstallationUseCase to run twice. The getActiveInstallationUseCase.execute() method returns a Promise, and I want it to execute only once when the user logs in.
I attempted to use the share() operator without success as shown below:
get(): Observable<State> {
return this.loginStore
.get()
.pipe(
switchMap(() => from(this.getActiveInstallationUseCase.execute()).pipe(map(x => ({ activeInstallation: x }))),
share()
)
}
And also tried:
get(): Observable<State> {
return this.loginStore
.get()
.pipe(
switchMap(() => from(this.getActiveInstallationUseCase.execute()).pipe(map(x => ({ activeInstallation: x }))), share()),
)
}
Despite these attempts, the method still runs twice. I have verified that this.loginStore.get() emits an event just once and even tried replacing share with shareReplay but couldn't resolve the issue.
I created a demo of the issue here. Currently, the promise is being called 4 times, whereas I want it to be executed only twice. While using the share() operator solves the problem in the demo, it doesn't work as expected in my actual code. Why is that happening?