簡體   English   中英

如何停止去抖動的 Rxjs Observable?

[英]How is it possible to stop a debounced Rxjs Observable?

我創建了一個 observable,它將在最后一次更改后 3 秒觸發,並調用服務的publishChange 它有效,但我想創建一個doImmediateChange function,它立即調用publishChange並停止去抖動的 observable。 這怎么可能?

我的組件:

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);

    }

}

您可以使用switchMapdelay模擬debounceTime 然后使用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);
}

https://stackblitz.com/edit/rxjs-ya93fb

使用競賽運算符

第一個完成的 observable 成為唯一訂閱的 observable,所以這個遞歸的 function 將在一次發射后完成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)
}

您可以使用debouncerace實現此行為:
使用您提供的代碼

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 秒),而不會延遲(感謝我們的種族可觀察)。

這是一個工作示例

您可以為每個值提供一個特定於值的去抖時間,並使用帶timer的去debounce來動態更改值的去抖時間。

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 似乎不想添加完整的解決方案,所以我擴展了方法)

debounceTime 的值僅在可觀察的創建時間評估一次。

為了能夠動態更新 debounceTime,請將 debounce 與計時器一起使用,如下所示:

 debounce(()=>timer(this.debounceTime)),

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM