← BACK

p-debounce

Debounce promise-returning & async functions

JavaScript ⭐ 238

p-debounce

Debounce promise-returning & async functions

Install

npm install p-debounce

Usage

import pDebounce from 'p-debounce';

const expensiveCall = async input => input;

const debouncedFunction = pDebounce(expensiveCall, 200);

for (const number of [1, 2, 3]) {
	(async () => {
		console.log(await debouncedFunction(number));
	})();
}
//=> 3
//=> 3
//=> 3

API

pDebounce(fn, wait, options?)

Returns a function that delays calling fn until after wait milliseconds have elapsed since the last time it was called.

fn

Type: Function

Promise-returning/async function to debounce.

wait

Type: number

Milliseconds to wait before calling fn. Must be at most 2147483647 (about 24.8 days).

options

Type: object

before

Type: boolean
Default: false

Call the fn on the leading edge of the timeout. Meaning immediately, instead of waiting for wait milliseconds.

The other calls in the same window resolve with the result of the leading call, so they settle only when the leading call settles.

[!NOTE]
fn must not wait for the promise of a call it makes to its own debounced function. That call waits for the leading call, so it never settles.

signal

Type: AbortSignal

An AbortSignal to cancel the debounced function.

pDebounce.promise(function_, options?)

Execute function_ unless a previous call is still pending, in which case, return the pending promise. Useful, for example, to avoid processing extra button clicks if the previous one is not complete.

[!NOTE]
function_ must not wait for the promise of a call it makes to its own debounced function. That call returns the pending promise (or is queued behind the running call with after: true), so it never settles.

import {setTimeout as delay} from 'timers/promises';
import pDebounce from 'p-debounce';

const expensiveCall = async value => {
	await delay(200);
	return value;
};

const debouncedFunction = pDebounce.promise(expensiveCall);

for (const number of [1, 2, 3]) {
	(async () => {
		console.log(await debouncedFunction(number));
	})();
}
//=> 1
//=> 1
//=> 1
function_

Type: Function

Promise-returning/async function to debounce.

options

Type: object

after

Type: boolean
Default: false

If a call is made while a previous call is still running, queue the latest arguments and run the function again after the current execution completes.

Each caller settles as soon as the execution it is waiting for completes. Calls queued during the same execution share the result of the latest one.

Use cases:

  • With after: false (default): API fetches, data loading, read operations - concurrent calls share the same result.
  • With after: true: Saving data, file writes, state updates - ensures latest data is never lost.
import {setTimeout as delay} from 'timers/promises';
import pDebounce from 'p-debounce';

const save = async data => {
	await delay(200);
	console.log(`Saved: ${data}`);
	return data;
};

const debouncedSave = pDebounce.promise(save, {after: true});

// If data changes while saving, it will save again with the latest data
debouncedSave('data1');
debouncedSave('data2'); // This will run after the first save completes
//=> Saved: data1
//=> Saved: data2

Recipes

Autosave

For autosave, combine trailing debounce with serialization to prevent concurrent saves from racing:

import pDebounce from 'p-debounce';

const saveDocument = async content => {
	await fetch('/api/save', {
		method: 'POST',
		body: JSON.stringify({content}),
	});
};

// Serialize saves, then debounce keystrokes
const serializedSave = pDebounce.promise(saveDocument, {after: true});
const autosave = pDebounce(serializedSave, 1000);

textArea.addEventListener('input', () => {
	autosave(textArea.value);
});

// 1. Waits 1s after typing stops
// 2. If user types during save, queues next save with latest content
// 3. Prevents race conditions where slow saves overwrite newer data

Related

  • p-throttle - Throttle promise-returning & async functions
  • p-limit - Run multiple promise-returning & async functions with limited concurrency
  • p-memoize - Memoize promise-returning & async functions
  • debounce-fn - Debounce a function
  • More…