我创建了一个可观察对象,它将在进行最后更改后3秒触发,并调用服务的publishChange
。它可以工作,但是我想创建一个doImmediateChange
函数,该函数立即调用publishChange
并停止去抖动的可观察对象。那怎么可能?
我的组件
class MyComponent {
private updateSubject = new Subject<string>();
ngOnInit() {
this.updateSubject.pipe(
debounceTime(3000),
distinctUntilChanged()
).subscribe(val => {
this.srv.publishChange(val);
});
}
doChange(val: string) {
this.updateSubject.next(val);
}
doImmediateChange(val: string) {
// Stop the current updateSubject if debounce is in progress and call publish immediately
// ??
this.srv.publishChange(val);
}
}
答案 0 :(得分:7)
您可以使用debounceTime
和switchMap
模拟delay
。然后使用takeUntil
取消内部的Observable,以防止发出等待值。
private updateSubject = new Subject<string>();
private interrupt = new Subject();
ngOnInit() {
this.updateSubject.pipe(
switchMap(val => of(val).pipe(
delay(3000),
takeUntil(this.interrupt)
))
).subscribe(val => publish(val));
}
doChange(val: string) {
this.updateSubject.next(val);
}
doImmediateChange(val: string) {
this.interrupt.next();
publish(val);
}
答案 1 :(得分:1)
第一个完成的可观察对象将成为已预订的仅,因此此递归函数将在发出take(1)
之后完成,然后重新订阅() => this.raceRecursive()
。
private timed$ = new Subject<string>();
private event$ = new Subject<string>();
ngOnInit() {
this.raceRecursive()
}
raceRecursive() {
race(
this.timed$.pipe(debounceTime(1000)),
this.event$
)
.pipe(take(1)) // force it to complete
.subscribe(
val => console.log(val), // srv call here
err => console.error(err),
() => this.raceRecursive() // reset it once complete
)
}
doChange(val: string) {
this.timed$.next(val)
}
doImmediateChange(val: string) {
this.event$.next(val)
}
答案 2 :(得分:1)
您可以使用debounce和race实现此行为:
加上您提供的代码
private destroy$ = new Subject<void>();
private immediate$ = new Subject<void>();
private updateSubject$ = new Subject<string>();
constructor(private srv: PubSubService) {}
ngOnInit() {
this.updateSubject$.pipe(
takeUntil(this.destroy$),
debounce(() => race(timer(3000), this.immediate$))
).subscribe(val => {
this.srv.publishChange(val);
});
}
doChange(val: string, immediate?: boolean) {
this.updateSubject$.next(val);
if (immediate) this.immediate$.next();
}
// don't forget to unsubscribe
ngOnDestroy() {
this.destroy$.next();
}
立即做出更改将取代之前的正常更改(被反跳3秒),而不会造成延迟(由于我们的种族可观察)。
这是工作中的example
答案 3 :(得分:1)
您可以为每个值提供特定于值的去抖动时间,并使用debounce
和timer
来动态更改值的去抖动时间。
private updateSubject = new Subject<{ value: any, debounceTime: number}>();
ngOnInit() {
updateSubject.pipe(
debounce(({ debounceTime }) => timer(debounceTime)),
pluck('value')
).subscribe(val => publish(val));
}
doChange(value: string) {
updateSubject.next({ value, debounceTime: 3000 });
}
doImmediateChange(value: string) {
updateSubject.next({ value, debounceTime: 0 });
}
这不会直接停止去抖动的Observable,但让我们用零延迟发出一个新值来“覆盖”一个等待值。
https://stackblitz.com/edit/rxjs-j15zyq
(user733421似乎不想添加完整的解决方案,所以我扩展了方法)
答案 4 :(得分:0)
debounceTime的值仅在可观察的创建时间上评估一次。
要能够动态更新debounceTime,请将debounce与计时器一起使用,如下所示:
debounce(()=>timer(this.debounceTime)),