I am currently facing an issue with the BehaviorSubject
where it emits a value for every subscription. This means that if I have, for example, 2 subscriptions to
this.projectService.projectState$
streams using methods like async
or tap
, the projectState$
emits twice. Similarly, if I have 3 streams, tap
will emit 3 times and so on. I have tried using distinctUntilChanged()
and shareReplay(1)
, but they do not seem to resolve the issue as BehaviorSubject
is already hot and does not require shareReplay(1)
.
project.service.ts:
projectState: BehaviorSubject<any> = new BehaviorSubject(null);
projectState$: Observable<any> = this.projectState.asObservable().pipe(
distinctUntilChanged(),
shareReplay(1),
tap(s => console.log("state", s)) // Outputs state twice
);
projectId$: Observable<string> = this.router.events.pipe(
startWith(new NavigationEnd(0, "", "")),
filter(event => event instanceof NavigationEnd),
map(_ => {
const { primary } = this.router.parseUrl(this.router.url).root.children;
const segments = primary && primary.segments;
return segments && segments[4] && segments[4].toString()
}),
filter(id => id && !["admin-areas", "profiles"].includes(id)),
distinctUntilChanged(),
shareReplay(1)
);
projectInfo$: Observable<any> = this.projectId$.pipe(
switchMap(id => this.getProjectInfo(id)),
shareReplay(1)
)
constructor(private http: HttpClient,
private appService: AppService,
private router: Router) {
this.projectInfo$.subscribe(
info => this.projectState.next(info)
)
}
header.component.ts
here 2
this.projectService.projectState$
streams subscribed via async
projectName$: Observable<string> = this.projectService.projectState$.pipe(
filter(info => info),
map(info => info.name)
);
versionName$: Observable<string> = this.projectService.projectState$.pipe(
filter(info => info),
map(info => info.modelVersionsList),
map(versions => versions.find(v => v.id === this.projectService.getCurrentVersionId())),
filter(v => v),
map(v => v.title)
);
header.component.html
<div>{{projectName$ | async}} - {{versionName$ | async} </div>