Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

timeout

Wraps a promise and rejects if it doesn't settle within the given time.

TypeScript
Copied!
1/**
2 * Wraps a promise and rejects if it doesn't settle within the given time.
3 *
4 * @param promise - The promise to wrap.
5 * @param ms - Timeout in milliseconds.
6 * @param message - Optional custom error message.
7 * @returns A promise that either resolves/rejects like the original or times out.
8 */
9export function timeout<T>(
10  promise: Promise<T>,
11  ms: number,
12  message = 'Operation timed out'
13): Promise<T> {
14  let timeoutId: ReturnType<typeof setTimeout>;
15
16  const timeoutPromise = new Promise<never>((_, reject) => {
17    timeoutId = setTimeout(() => reject(new Error(message)), ms);
18  });
19
20  return Promise.race([
21    promise.finally(() => clearTimeout(timeoutId)),
22    timeoutPromise
23  ]);
24}
  • Timeout Enforcement for Promises

    Rejects a promise if it takes too long to settle, helping prevent hanging async operations.

  • Custom Error Messaging

    Allows an optional custom error message, improving debuggability and user feedback.

  • Resource Cleanup

    Automatically clears the timeout using finally(), ensuring no lingering timers.

  • Composable and Transparent

    Doesn’t interfere with the original promise logic — simply wraps it with a time constraint.

Tests | Examples

TypeScript
Copied!
1function delayedResolve<T>(value: T, delay: number): Promise<T> {
2  return new Promise(resolve => setTimeout(() => resolve(value), delay));
3}
4
5test('timeout - resolves before timeout', async () => {
6  const result = await timeout(delayedResolve('done', 50), 100);
7  expect(result).toBe('done');
8});
9
10test('timeout - rejects after timeout', async () => {
11  await expect(timeout(delayedResolve('late', 100), 50)).rejects.toThrow(
12    'Operation timed out'
13  );
14});
15
16test('timeout - uses custom error message', async () => {
17  await expect(timeout(delayedResolve('late', 100), 50, 'Too slow')).rejects.toThrow('Too slow');
18});

Common Use Cases

  • API and Network Request Protection

    Prevent long-running or stalled HTTP calls from blocking app logic or degrading UX.

  • User Interaction Feedback

    Enforce time limits for operations like file uploads, authentication, or remote validation.

  • Async Task Deadlines

    Apply soft execution deadlines to background tasks or parallel jobs.

  • Testing Slow Code

    Catch performance regressions or unintended hangs during unit or integration tests.

  • External System Fallbacks

    Trigger fallback logic when a third-party service or resource is unresponsive beyond an acceptable threshold.

Codebase: Utilities -> Functions -> timeout | Yevhen Klymentiev