Timeout a promise after a specified amount of time
npx @tessl/cli install tessl/npm-p-timeout@6.1.0p-timeout provides a utility for adding timeout functionality to JavaScript promises, allowing developers to set time limits on asynchronous operations. It offers a simple API that wraps any promise and automatically rejects it with a TimeoutError if it doesn't resolve within the specified milliseconds.
npm install p-timeoutimport pTimeout, { TimeoutError, AbortError } from 'p-timeout';Individual imports:
import { TimeoutError, AbortError } from 'p-timeout';import { setTimeout } from 'node:timers/promises';
import pTimeout from 'p-timeout';
const delayedPromise = setTimeout(200);
// Timeout after 50ms - will throw TimeoutError
await pTimeout(delayedPromise, {
milliseconds: 50,
});
//=> [TimeoutError: Promise timed out after 50 milliseconds]Add timeout functionality to any promise with configurable error handling and cancellation support.
/**
* Timeout a promise after a specified amount of time
* @param input - Promise to decorate
* @param options - Timeout configuration options
* @returns A decorated promise that times out after specified milliseconds with a .clear() method
*/
function pTimeout<ValueType, ReturnType = ValueType>(
input: PromiseLike<ValueType>,
options: Options<ReturnType>
): ClearablePromise<ValueType | ReturnType>;
// Special overload for message: false case
function pTimeout<ValueType, ReturnType = ValueType>(
input: PromiseLike<ValueType>,
options: Options<ReturnType> & {message: false}
): ClearablePromise<ValueType | ReturnType | undefined>;Usage Examples:
import pTimeout from 'p-timeout';
import { setTimeout } from 'node:timers/promises';
// Basic timeout
const result = await pTimeout(setTimeout(200, 'success'), {
milliseconds: 100, // Will timeout
});
// Custom error message
try {
await pTimeout(longRunningOperation(), {
milliseconds: 5000,
message: 'Operation took too long'
});
} catch (error) {
console.log(error.message); // 'Operation took too long'
}
// Silent timeout (resolves undefined instead of throwing)
const result = await pTimeout(slowPromise(), {
milliseconds: 1000,
message: false
});
// result will be undefined if timeout occurs
// Fallback function on timeout
const result = await pTimeout(unreliableAPI(), {
milliseconds: 3000,
fallback: () => 'default value'
});
// Clear timeout manually
const timeoutPromise = pTimeout(operation(), { milliseconds: 5000 });
// Later... cancel the timeout
timeoutPromise.clear();Support for modern cancellation using AbortController signals.
// AbortController support through options.signal
interface Options<ReturnType> {
signal?: AbortSignal;
// ... other options
}Usage Example:
import pTimeout from 'p-timeout';
const delayedPromise = new Promise(resolve => setTimeout(resolve, 3000));
const abortController = new AbortController();
// Cancel after 100ms
setTimeout(() => {
abortController.abort();
}, 100);
await pTimeout(delayedPromise, {
milliseconds: 2000,
signal: abortController.signal
});
// Will throw AbortError or DOMException after 100msCustom error classes for different timeout and cancellation scenarios.
/**
* Error thrown when a promise times out
*/
class TimeoutError extends Error {
readonly name: 'TimeoutError';
constructor(message?: string);
}
/**
* Error thrown when request is aborted by AbortController
* (fallback when DOMException not available)
*/
class AbortError extends Error {
readonly name: 'AbortError';
constructor(message?: string);
}Usage Example:
import pTimeout, { TimeoutError } from 'p-timeout';
try {
await pTimeout(slowOperation(), { milliseconds: 1000 });
} catch (error) {
if (error instanceof TimeoutError) {
console.log('Operation timed out');
}
}
// Custom error subclassing
class MyCustomError extends TimeoutError {
name = "MyCustomError";
}
await pTimeout(operation(), {
milliseconds: 5000,
message: new MyCustomError('Custom timeout message')
});Custom timer implementations for testing scenarios and fake timer compatibility.
interface Options<ReturnType> {
customTimers?: {
setTimeout: typeof globalThis.setTimeout;
clearTimeout: typeof globalThis.clearTimeout;
};
// ... other options
}Usage Example:
import pTimeout from 'p-timeout';
import sinon from 'sinon';
const originalSetTimeout = setTimeout;
const originalClearTimeout = clearTimeout;
sinon.useFakeTimers();
// Use pTimeout without being affected by sinon.useFakeTimers()
await pTimeout(doSomething(), {
milliseconds: 2000,
customTimers: {
setTimeout: originalSetTimeout,
clearTimeout: originalClearTimeout
}
});Automatic integration with promises that have a .cancel() method.
// When input promise has .cancel() method, it will be called on timeout
// No special API required - works automaticallyUsage Example:
import pTimeout from 'p-timeout';
import PCancelable from 'p-cancelable';
const cancelablePromise = new PCancelable((resolve, reject, onCancel) => {
const timeoutId = setTimeout(resolve, 5000);
onCancel(() => {
clearTimeout(timeoutId);
reject(new Error('Canceled'));
});
});
// If timeout occurs, cancelablePromise.cancel() will be called automatically
await pTimeout(cancelablePromise, { milliseconds: 1000 });/**
* Promise with additional clear() method to cancel timeout
*/
type ClearablePromise<T> = {
clear: () => void;
} & Promise<T>;
/**
* Configuration options for pTimeout function
*/
interface Options<ReturnType> {
/** Milliseconds before timing out (required) */
milliseconds: number;
/** Custom error message, error to throw, or false to resolve undefined */
message?: string | Error | false;
/** Function to call on timeout instead of rejecting */
fallback?: () => ReturnType | Promise<ReturnType>;
/** Custom timer implementations for testing */
readonly customTimers?: {
setTimeout: typeof globalThis.setTimeout;
clearTimeout: typeof globalThis.clearTimeout;
};
/** AbortController signal for cancellation */
signal?: globalThis.AbortSignal;
}Infinity will cause it to never time outTypeErrorDOMException when available, falls back to AbortError.cancel() method on cancelable promises during timeout