I let a user scroll a page and in every scroll event - I'm checking if there's a new items in the viewport
( if there are , I do some operation on those new items - irrelevant for now).
So I have something like this :
const observable = Rx.Observable.fromEvent(window, 'scroll');
const subscriber = observable.throttleTime(300 /* ms */).subscribe(
(x) => {
console.log('Next: event!');
},
(err) => {
console.log('Error: %s', err);
},
() => {
console.log('Completed');
});
This code is working as expected and I do see a message after each 300 ms.
But there's a problem. A user might scroll while not completing the 300 ms ( event won't be raised) and a new item got visible while scrolling.
This is where I need the debounce
method. (which means "after X ms of last event time - raise an event")
Which is exactly what I need.
I've tried this :
const subscriber = observable.throttleTime(300 /* ms */).debounceTime(350)....
But I only see the debounced events.
Question
How can I use throttle and at the end of a throttle - attach a debounce ?
Throttle is normally used when you have a function that is called continuously while the user is interacting with your page, e.g. while scrolling. Debounce is used to call a function when the user has stopped interacting, e.g. when they have stopped typing in an input field. Let's say a function is fired many times.
It's simple. They do the exact same thing (rate limiting) except while throttle is being called it'll fire your function periodically, while debounce only fires once at the end. Example: If you're scrolling, throttle will slowly call your function while you scroll (every X milliseconds).
debounceTime delays the values emitted by a source for the given due time. If within this time a new value arrives, the previous pending value is dropped and the timer is reset. In this way debounceTime keeps track of most recent value and emits that most recent value when the given due time is passed.
here is updated solution due to rxjs changes
import { fromEvent } from 'rxjs';
import { debounceTime, map, throttleTime } from 'rxjs/operators';
const observable = fromEvent(window, 'scroll');
const subscriber = observable
.pipe(
throttleTime(300 /* ms */),
map((data) => {
console.log('throttle');
console.log(window.pageYOffset);
return data;
}),
debounceTime(350)
)
.subscribe(
(x) => {
console.log(window.pageYOffset);
},
(err) => {
console.log('Error: %s', err);
},
() => {
console.log('Completed');
}
);
You could merge two streams: throttled and debounced into one using merge
. Demo.
const observable = Rx.Observable.fromEvent(window, 'scroll');
const subscriber = observable
.throttleTime(300 /* ms */)
.map(() => 'throttle')
.merge(observable
.debounceTime(350)
.map(() => 'debounce')
)
.subscribe(
(x) => {
console.log('Next: event!', x);
},
(err) => {
console.log('Error: %s', err);
},
() => {
console.log('Completed');
});
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