Delay is a lightweight Promise-based utility for delaying execution in JavaScript applications. It provides precise timing control with support for AbortController cancellation, value resolution, random delays, and custom timeout implementations for testing scenarios.
npm install delayimport delay from 'delay';
import { rangeDelay, clearDelay, createDelay } from 'delay';For CommonJS:
const delay = require('delay');
const { rangeDelay, clearDelay, createDelay } = require('delay');import delay from 'delay';
// Basic delay
bar();
await delay(100);
// Executed 100 milliseconds later
baz();
// Delay with resolved value
const result = await delay(100, { value: '🦄' });
console.log(result); //=> '🦄'
// Cancellable delay
const abortController = new AbortController();
setTimeout(() => abortController.abort(), 500);
try {
await delay(1000, { signal: abortController.signal });
} catch (error) {
console.log(error.name); //=> 'AbortError'
}Delay is built around several key design patterns:
createDelay allows custom timer implementations for testing environments or specialized use casesclearDelay functionalityThe package maintains minimal overhead while providing maximum flexibility through these architectural choices.
Creates a Promise that resolves after a specified number of milliseconds.
/**
* Create a promise which resolves after the specified milliseconds
* @param milliseconds - Milliseconds to delay the promise (0 for next tick)
* @param options - Configuration options
* @returns Promise that resolves with the provided value after the delay
*/
function delay<T>(milliseconds: number, options?: Options<T>): Promise<T>;Note: While the TypeScript definition requires the milliseconds parameter, the runtime implementation treats undefined as 0, allowing delay() to work in plain JavaScript. In TypeScript, use delay(0) for next-tick behavior.
Usage Examples:
// Simple delay
await delay(1000); // Wait 1 second
// Delay with 0ms (next tick) - note: TypeScript requires explicit 0
await delay(0);
// Delay with value
const greeting = await delay(500, { value: 'Hello!' });
console.log(greeting); //=> 'Hello!'
// Cancellable delay
const controller = new AbortController();
const delayPromise = delay(2000, {
value: 'Done',
signal: controller.signal
});
// Cancel after 1 second
setTimeout(() => controller.abort(), 1000);
try {
await delayPromise;
} catch (error) {
console.log(error.name); //=> 'AbortError'
}Creates a Promise that resolves after a random number of milliseconds between minimum and maximum values.
/**
* Create a promise which resolves after a random amount of milliseconds
* @param minimum - Minimum amount of milliseconds to delay the promise
* @param maximum - Maximum amount of milliseconds to delay the promise
* @param options - Configuration options
* @returns Promise that resolves after a random delay between minimum and maximum
*/
function rangeDelay<T>(minimum: number, maximum: number, options?: Options<T>): Promise<T>;Usage Examples:
// Random delay between 100-500ms
await rangeDelay(100, 500);
// Random delay with value
const result = await rangeDelay(50, 150, { value: 'random!' });
// Random delay with abort signal
const controller = new AbortController();
await rangeDelay(200, 800, { signal: controller.signal });Immediately clears a delay and resolves the promise with its intended value.
/**
* Clears the delay and settles the promise
* @param delayPromise - The delay promise to clear
* @returns void
*/
function clearDelay(delayPromise: Promise<unknown>): void;Usage Examples:
const delayPromise = delay(1000, { value: 'Done' });
// Clear after 500ms instead of waiting 1000ms
setTimeout(() => {
clearDelay(delayPromise);
}, 500);
// Still resolves with 'Done' but much faster
console.log(await delayPromise); //=> 'Done'
// Safe to call on non-delay promises (does nothing)
clearDelay(Promise.resolve('not a delay'));Creates a new delay function using custom setTimeout and clearTimeout implementations.
/**
* Creates a new delay instance using provided timer functions
* @param timers - Object with custom timer implementations
* @param timers.setTimeout - Custom setTimeout function
* @param timers.clearTimeout - Custom clearTimeout function
* @returns New delay function with same signature as default delay
*/
function createDelay(timers: {
clearTimeout: (timeoutId: any) => void;
setTimeout: (callback: (...args: any[]) => void, milliseconds: number, ...args: any[]) => unknown;
}): typeof delay;Usage Examples:
// Useful for testing with fake timers
import { createDelay } from 'delay';
const customDelay = createDelay({
setTimeout: myMockSetTimeout,
clearTimeout: myMockClearTimeout
});
// Use like normal delay but with custom timer implementation
await customDelay(100, { value: 'test' });
// Node.js example with unref to prevent hanging
const unrefDelay = createDelay({
clearTimeout,
setTimeout(...args) {
return setTimeout(...args).unref();
}
});interface Options<T> {
/**
* A value to resolve in the returned promise
*/
value?: T;
/**
* An AbortSignal to abort the delay
* The returned promise will be rejected with an AbortError if aborted
*/
signal?: AbortSignal;
}The delay functions can throw the following errors:
error.name will be 'AbortError'error.message will be 'Delay aborted'try {
const controller = new AbortController();
controller.abort(); // Abort immediately
await delay(1000, { signal: controller.signal });
} catch (error) {
console.log(error.name); //=> 'AbortError'
console.log(error.message); //=> 'Delay aborted'
}The package uses standard setTimeout and clearTimeout by default, making it compatible across environments. Custom timer implementations can be provided via createDelay for testing or specialized use cases.