我想从服务中执行 toggleButtonOnClick$()
函数,只有当我点击一个按钮时。此函数将保存当前状态,服务稍后将收到此更改并更新 usersObs$。
每当发生上述情况时,toggleButtonOnClick$
都会再执行几次,即使我没有再次点击该按钮。
如何防止这种情况发生并使此函数仅在我对 clickSubject 执行 .next()
而不是在 userObs$ 更改时执行?
我会写一个例子来说明整个情况
按钮组件
private userClick = new Subject<null>();
private obs1$: Observable<string>();
private obs2$: Observable<string>();
private obs3$: Observable<boolean>();
ngOnInit(): void {
this.obs2$ = this.obs1$.pipe(
switchMap((value) => this.someService.getSomePropBasedOnValue$(value))
);
this.obs3$ = this.obs2$.pipe(
switchMap((value) => this.someService.checksAndReturnsBoolean$(value))
this.subscriptions.add(
this.someService.toggleButtonOnClick$(this.obs2$, this.userClick).subscribe()
)
}
ngOnDestroy(): void {
this.subscriptions.unsuscribe();
}
onClick(): void {
// emit a value when click on button to start observable chain
this.userClick.next();
}
HTML
<div
[attr.tooltip]="(obs3$ | async) ?
('text_translation_1' | transloco)
: ('text_translation_2' | transloco)"
>
<span
*ngIf="(obs3$ | async) && !isHovering"
>
Something here
</span>
<span
*ngIf="(obs3$ | async) && isHovering"
>
Something here
</span>
<span
*ngIf="!(obs3$ | async)"
>
Something here
</span>
</div>
SomeService
public checksAndReturnsBoolean$(id): Observable<boolean> {
return this.userObs$.pipe(
map((users) => { users.some(((user) => user.id === id)) }
);
}
public getSomePropBasedOnValue$(id): Observable<SomeObject | null> {
return this.userObs$.pipe(
map((users) => { users.find(((user) => user.id === id)) ?? null }
);
}
public toggleButtonOnClick$(obs2$, userClick): Observable<void> {
return userClick.pipe(
switchMap(() => obs3$),
switchMap((id) => combineLatest([this.getSomeDataById$(id), of(id)]))
).pipe(
map(([data, id]) => {
// some code block that gets executed everytime an observable emits new value
})
);
一切完成后,我会尝试在点击后存储用户的决定。所以 userObs$ 得到更新,一旦发生这种情况,toggleButtonOnClick$ 中的块将再次执行,不是一次,而是 2 有时 3 或 4。
顺便说一句,在组件中,obs2$ 使用异步管道在 DOM 上显示/隐藏内容。也许这也是在服务可观察更改后触发调用。
我已经尝试了几件事,但都没有运气。
任何提示或帮助或指导将不胜感激。
谢谢。
答案 0 :(得分:0)
我需要的是在我的服务的不同功能上使用 shareReplay(1) 和 take(1) 以使其按预期工作,而不会重复不必要的调用。
它最终看起来像这样:
public checksAndReturnsBoolean$(id): Observable<boolean> {
return this.userObs$.pipe(
map((users) => { users.some((user) => user.id === id) }),
take(1)
);
}
public getSomePropBasedOnValue$(id): Observable<SomeObject | null> {
return this.userObs$.pipe(
map((users) => { users.find((user) => user.id === id) ?? null }),
shareReplay(1)
);
}