У меня проблема с BehaviorSubject
выбрасывает значение для каждой подписки. Поэтому, если у меня есть, например, 2 this.projectService.projectState$
потоков, подписанных через, например, async
, tap
на projectState$
, излучается дважды. Соответственно если у меня 3 потока, tap
излучает 3 раза и так далее. Я думаю, что это похоже на эту проблему Почему RXJS угловое поведение Subject выдает множественные значения , но предложенные ответы мне не подходят. Помимо distinctUntilChanged()
я использовал shareReplay(1)
, но, насколько я понимаю, Observable
делает его горячим, но BehaviorSubject
уже горячий и не нуждается в 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)) // logged twice the same state
);
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
здесь 2 this.projectService.projectState$
потоков, подписанных через 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>