Home Reference Source Repository

src/operators/debounce.js

/**
 * Debounce delays values emitted by the source stream, and drops previous
 * pending delayed emissions if a new value arrives on source stream.
 *
 * @example
 * import { Subject, debounce } from 'rxstream';
 *
 * let clicks$ = new Subject();
 * let debounced$ = debounce(Subject, clicks$, () => {
 *  let timer$ = new Subject();
 *
 *  setInterval(() => timer$.next(), 1000);
 *
 *  return timer$;
 * });
 *
 * document.addEventListener('click', (event) => {
 *  clicks$.next(new Date());
 * });
 *
 * debounced$.subscribe((event) => console.log(event));
 *
 * @function debounce<T>
 * @param {Subject|BehaviorSubject|ReplaySubject} SubjectConstructor Pass a constructor of result/filtered stream
 * @param {Subject|BehaviorSubject|ReplaySubject} stream$ Stream to be debounced
 * @param {function(value: T): Subject} conditionStreamGenerator a function that should return a stream, when new value arrives on that stream, debounced stream emits latest value from the source stream
 * @returns {Subject|BehaviorSubject|ReplaySubject}
 */
export function debounce(SubjectConstructor, stream$, conditionStreamGenerator) {
  let debouncedStream$ = new SubjectConstructor();
  let latestValue = null;
  let latestSubscription;
  let conditionStream$;

  stream$.subscribe((payload) => {
    latestValue = payload;
    (conditionStream$) ? conditionStream$.unsubscribe(latestSubscription) : null;

    conditionStream$ = conditionStreamGenerator();
    latestSubscription = conditionStream$.subscribe(() => {
      debouncedStream$.next(latestValue);
      conditionStream$.unsubscribe(latestSubscription);
    });
  });

  return debouncedStream$;
}