Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS - debounce event after throttle?

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 ?

like image 556
Royi Namir Avatar asked Mar 31 '17 21:03

Royi Namir


People also ask

Should I throttle or debounce scroll?

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.

What is the difference between debounce time and throttle time?

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).

What does debounce time do RXJS?

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.


2 Answers

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');
    }
  );
like image 189
Eric Aska Avatar answered Sep 22 '22 11:09

Eric Aska


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');
          });
like image 38
Yury Tarabanko Avatar answered Sep 23 '22 11:09

Yury Tarabanko