【问题标题】:rxjs: cancelling a debounced observablerxjs:取消去抖动的 observable
【发布时间】:2021-02-20 00:51:53
【问题描述】:

我有一个可观察的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 的情况下只取消去抖动的发射?

【问题讨论】:

  • 看起来你可以只使用repeat() 而不是repeatWhen(),因为你只使用了主题,所以你保持订阅源 Observable 并不重要。

标签: rxjs


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 2021-04-14
    相关资源
    最近更新 更多