Royi Namir
Royi Namir

Reputation: 148524

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 ?

Upvotes: 11

Views: 5355

Answers (2)

Eric Aska
Eric Aska

Reputation: 636

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');
    }
  );

Upvotes: 2

Yury Tarabanko
Yury Tarabanko

Reputation: 45121

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');
          });

Upvotes: 8

Related Questions