javascript-RxJS:使用常规采样进行反跳

我有一个Observable,它从用户输入发出一个值流(滑块的偏移值).

我想对流进行去抖动,因此,当用户忙于滑动时,我只会在没有发生任何事情(例如100ms)的情况下发出一个值,以避免被值淹没.但是然后我也想每隔1秒钟发出一个值,如果它只是不断地反跳(用户不断地来回滑动).一旦用户停止滑动,我只想从去抖动的流中得到最终值.

因此,我想将反跳与流的常规“采样”结合在一起.现在我的设置是这样的:

const debounce$= slider$.debounceTime(100),
      sampler$= slider$.auditTime(1000);

debounce$
    .merge(sampler$)
    .subscribe((value) => console.log(value));

假设用户将滑块移动2.4秒钟,则会发出如下值:

 start                      end
  (x)---------|---------|---(x)|----|
              |         |      |    |
             1.0       2.0    2.5  3.0  <-- unwanted value at the end
              ^         ^      ^
            sample   sample   debounce  <-- these are all good

我不希望3秒(从sampler $流中)发出额外的值.

显然,合并是合并这两个流的错误方法,但是我无法弄清楚在这里要使用哪种开关,种族,窗口或任何组合.

解决方法:

您可以通过组成一个可观察的信号来解决该问题,该信号可指示用户当前是否在滑动.应该这样做:

const sliding$= slider$.mapTo(true).merge(debounce$.mapTo(false));

您可以使用它来控制sampler $是否发出值.

一个工作示例:

const since = Date.now();
const slider$= new Rx.Subject();

const debounce$= slider$.debounceTime(100);
const sliding$= slider$.mapTo(true).merge(debounce$.mapTo(false));

const sampler$= slider$
  .auditTime(1000)
  .withLatestFrom(sliding$)
  .filter(([value, sliding]) => sliding)
  .map(([value]) => value);

debounce$
  .merge(sampler$)
  .subscribe(value => console.log(`${time()}: ${value}`));

// Simulate sliding:

let value = 0;
for (let i = 0; i <= 2400; i += 10) {
  value += Math.random() > 0.5 ? 1 : -1;
  slide(value, i);
}

function slide(value, at) {
  setTimeout(() => slider$.next(value), at);
}

function time() {
  return `T+${((Date.now() - since) / 1000).toFixed(3)}`;
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
上一篇:javascript – 为什么first()rxjs运算符会继续返回数组


下一篇:javascript – Rxjs:将两个流合并为一个依赖于另一个流的流