Skip to main content
Creates a debounced function that delays invoking fn until after waitMs milliseconds have elapsed since the last time the debounced function was invoked.

Signature

function debounce<Args extends unknown[], R>(
  fn: (...args: Args) => PromiseLike<R> | R,
  waitMs: number,
  options?: DebounceOptions,
): (...args: Args) => Promise<R>

Parameters

fn
(...args: Args) => PromiseLike<R> | R
required
The function to debounce. Can be sync or async.
waitMs
number
required
The number of milliseconds to delay.
options
DebounceOptions
Debounce configuration options.

Returns

A debounced version of the function that returns a promise.

Examples

Basic debounce

import { debounce } from '@temelj/async';

const search = debounce(async (query: string) => {
  const results = await api.search(query);
  return results;
}, 300);

// Only the last call executes after 300ms
search('a');
search('ab');
search('abc'); // This call executes

Leading edge execution

import { debounce } from '@temelj/async';

const handleClick = debounce(
  async () => {
    await submitForm();
  },
  1000,
  { leading: true, trailing: false }
);

// Executes immediately on first click, then ignores subsequent clicks for 1s
handleClick();
handleClick(); // Ignored
handleClick(); // Ignored

With abort signal

import { debounce } from '@temelj/async';

const controller = new AbortController();

const autosave = debounce(
  async (data: string) => {
    await saveToServer(data);
  },
  500,
  { signal: controller.signal }
);

autosave('draft 1');
autosave('draft 2');

// Cancel pending autosave
controller.abort();

Search input debouncing

import { debounce } from '@temelj/async';

const debouncedSearch = debounce(async (query: string) => {
  if (!query) return [];
  const response = await fetch(`/api/search?q=${query}`);
  return await response.json();
}, 300);

input.addEventListener('input', async (e) => {
  const results = await debouncedSearch(e.target.value);
  displayResults(results);
});

Build docs developers (and LLMs) love