【问题标题】:Debounce without initial delay无初始延迟的去抖动
【发布时间】:2017-03-29 18:11:51
【问题描述】:

RxJS 中是否有一个操作符在不延迟“突发中的第一个事件”的情况下进行去抖动,但延迟(并且总是发出)“突发中的最后一个事件”?

类似这样的:

---a----b-c-d-----e-f---

awesome-debounce(2 dashes) 之后变为:

---a----b------d--e----f

而正常的去抖动是:

-----a---------d-------f

这是一种混合了油门和去抖动...

【问题讨论】:

  • 所以你想让它在一个时间窗口内发出第一个和最后一个事件?
  • 是的,但是时间窗口的行为与 debounce 类似(它会随着窗口内的每个事件而扩展)。
  • 这才是真正的答案! *.com/a/30145789/684869

标签: rxjs reactive-programming


【解决方案1】:

嗯,这是我能想到的最简单的解决方案。对您来说有趣的部分是创建子链的 awesomeDebounce() 函数。

它基本上只是结合了throttle()debounceTime() 运算符:

const Rx = require('rxjs');
const chai = require('chai');

let scheduler = new Rx.TestScheduler((actual, expected) => {
  chai.assert.deepEqual(actual, expected);
  console.log(actual);
});

function awesomeDebounce(source, timeWindow = 1000, scheduler = Rx.Scheduler.async) {
  let shared = source.share();
  let notification = shared
      .switchMap(val => Rx.Observable.of(val).delay(timeWindow, scheduler))
      .publish();

  notification.connect();

  return shared
    .throttle(() => notification)
    .merge(shared.debounceTime(timeWindow, scheduler))
    .distinctUntilChanged();
}

let sourceMarbles =   '---a----b-c-d-----e-f---';
let expectedMarbles = '---a----b------d--e----f';

// Create the test Observable
let observable = scheduler
  .createHotObservable(sourceMarbles)
  .let(source => awesomeDebounce(source, 30, scheduler));

scheduler.expectObservable(observable).toBe(expectedMarbles);
scheduler.flush();

内部的notification Observable 仅用于throttle() 运算符,因此我可以在需要时手动重置其计时器。我还必须把这个 Observable 变成 "hot" 以独立于来自throttle() 的内部订阅。

【讨论】:

  • 我将奖励这个答案以奖励大理石测试的精彩演示和包含。等待 24 小时等待
【解决方案2】:

对于许多情况,这确实是有用的去抖动类型。在下一个方式中使用mergethrottleTimedebounceTime

Rx.Observable.merge(source.throttleTime(1000), source.debounceTime(2000))

完整的例子在这里http://jsbin.com/godocuqiwo/edit?js,console

注意:它不仅会发出去抖动间隔中的第一个和最后一个值,还会发出油门产生的值(这通常是预期和需要的,例如滚动去抖动)。

【讨论】: