首页 > 解决方案 > rxjs:取消去抖动的 observable

问题描述

我有一个可观察的Subject,它通过去抖动发出一些变化:

someSubject.pipe(
  debounceTime(5000),
).subscribe(response => {
  console.log('Value is', response);
})

现在,我需要Stop屏幕上某处的按钮来取消我的去抖动发射。所以我创建了一个按钮:

const stopObs = new Subject();
...
<button onClick={() => stopObs.next()}>Stop</button>

并像这样修改我的订阅:

someSubject.pipe(
  debounceTime(5000),
  takeUntil(stopObs),
).subscribe(response => {
  console.log('Value is', response);
})

这很好用,在点击“停止”后,我停止在控制台中获取值,但有一个问题:可观察对象永远停止。我需要它能够发出新的值,我只需要取消已经开始的去抖动发射。

我的第一个想法是创建一个新主题并使用repeatWhen

const startObs = new Subject();
...
<button onClick={() => startObs.next()}>Start</button>

...
someSubject.pipe(
  debounceTime(5000),
  takeUntil(stopObs),
  repeatWhen(() => startObs)
).subscribe(response => {
  console.log('Value is', response);
})

但是还有另一个问题:如果我多次点击“开始”按钮并发出多个值到startObs,那么我开始为单个去抖动值获得多个console.log'!

那么有没有办法在不停止整个 observable 的情况下只取消 debounced 发射?

标签: rxjs

解决方案


因为debounceTime只是

const duration = timer(dueTime, scheduler);
return debounce(() => duration);

我认为您可以像这样解决问题:

someSubject.pipe(
  debounce(() => timer(5000).pipe(takeUntil(stopObs))),
)

如果你想在定时器因 取消时发送最后一个值stopObs,你可以试试这个:

someSubject.pipe(
  debounce(
    () => timer(5000)
      .pipe(
        takeUntil(stopObs),
        isEmpty(),
      )
  ),
)

isEmpty()将在通知true之前立即发出,这是发送最后收到的值所需要的。如果计时器在没有' 参与的情况下完成,将发出而不是,但这仍然适用于,因为它只需要来自内部 observable 的值。completedebouncestopObsisEmptyfalsetruedebounce


推荐阅读