All files / core/src/utils debounce.ts

100% Statements 29/29
100% Branches 7/7
100% Functions 3/3
100% Lines 29/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 631x                                                       1x 15x 15x   15x 25x 1x 1x 1x   25x   25x   25x 24x 13x 13x 13x 1x 13x 13x 13x 24x 24x 25x   15x 3x 3x 3x   15x 15x  
import { captureStack } from '../exception.js';
 
/**
 * Type representing a debounce handler function that takes no arguments and returns void.
 */
export type DebounceHandler = () => void;
 
/**
 * Type representing a debounce scheduler function that accepts a debounce handler to be scheduled.
 */
export type DebounceScheduler = (fn: DebounceHandler) => void;
 
/**
 * Type representing a debounce cleaner function that clears any pending debounce operations.
 */
export type DebounceCleaner = () => void;
 
/**
 * Type representing a debouncer tuple containing both the scheduler and cleaner functions.
 */
export type Debouncer = [DebounceScheduler, DebounceCleaner];
 
/**
 * Creates a debounced function pair consisting of a scheduler and a cleaner.
 *
 * @param delay - The delay in milliseconds to wait before executing the scheduled function. Defaults to 10ms.
 * @returns A tuple containing the scheduler function at index 0 and the cleaner function at index 1.
 */
export function debouncer(delay = 10): Debouncer {
  let handler: DebounceHandler | undefined;
  let activeId: number | undefined;
 
  const schedule = ((fn) => {
    if (typeof fn !== 'function') {
      const error = new Error('Invalid argument.');
      captureStack.error.argument('The given argument is not a function.', error, schedule);
    }
 
    clearTimeout(activeId);
 
    handler = fn;
 
    if (typeof fn === 'function') {
      activeId = setTimeout(() => {
        try {
          handler?.();
        } catch (error) {
          captureStack.error.external('Debounce execution failed.', error as Error);
        } finally {
          handler = activeId = undefined;
        }
      }, delay);
    }
  }) as DebounceScheduler;
 
  const cleanup = (() => {
    clearTimeout(activeId);
    handler = activeId = undefined;
  }) as DebounceCleaner;
 
  return [schedule, cleanup];
}