Is there an operator in RxJS that debounces without delaying the "first event in a burst", but delaying (and always emitting) the "last event in a burst"?
Something like this:
---a----b-c-d-----e-f---
after awesome-debounce(2 dashes)
becomes:
---a----b------d--e----f
while a normal debounce would be:
-----a---------d-------f
It's kind of a mix between throttle and debounce...
# Throttling tells us the maximum number of times a function can be called over a period of time. It executes the function once every 100 milliseconds. # Debouncing means that a function will not be called again until a certain amount of time has passed without it being called.
What is debounce? Debounce delays the processing of a function bound to a certain user input event until a certain amount of time has passed. In other words the function is only executed once per specific user input event, even it the event is triggered multiple times.
throttleTime emits the source Observable values on the output Observable when its internal timer is disabled, and ignores source values when the timer is enabled. Initially, the timer is disabled. As soon as the first source value arrives, it is forwarded to the output Observable, and then the timer is enabled.
Hmmm, this is the easiest solution I can think of. The interesting part for you is the awesomeDebounce()
function that creates the sub-chain.
It basically just combines throttle()
and debounceTime()
operators:
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();
The inner notification
Observable is used only for the throttle()
operator so I can reset its timer manually when I need. I also had to turn this Observable into "hot" to be independent on the internal subscriptions from throttle()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With