Overview
The sleep function provides a Promise-based delay that can be automatically cancelled when used within a resilient function with timeout or abort signal support.
Function Signature
function sleep(
ms: number,
signal?: AbortSignal
): Promise<void>
Parameters
Duration to sleep in milliseconds.
signal
AbortSignal | undefined
default:"activeSignal"
Optional abort signal to enable cancellation. If not provided, automatically uses the active signal from the current resilient execution context (if any).When the signal is aborted, the sleep promise rejects with an Error('Aborted').
Return Value
A promise that resolves after the specified duration, or rejects if the abort signal is triggered.
Implementation Details
From src/index.ts:173-192, the function:
- Creates a timeout using
setTimeout
- If an abort signal is provided or available from context:
- Checks if signal is already aborted and rejects immediately
- Listens for abort events and clears the timeout
- Rejects the promise with an “Aborted” error when cancelled
- If no signal is available, behaves like a simple delay
export const sleep = (ms: number, signal: AbortSignal | undefined = activeSignal) =>
new Promise<void>((resolve, reject) => {
const id = setTimeout(resolve, ms);
if (!signal) return;
if (signal.aborted) {
clearTimeout(id);
reject(new Error('Aborted'));
return;
}
signal.addEventListener(
'abort',
() => {
clearTimeout(id);
reject(new Error('Aborted'));
},
{ once: true }
);
});
Examples
Basic Usage
import { sleep } from '@oldwhisper/resilience';
// Simple delay
await sleep(1000); // Wait 1 second
console.log('Done waiting');
With Manual Abort Signal
const controller = new AbortController();
// Start a sleep that can be cancelled
const sleepPromise = sleep(5000, controller.signal);
// Cancel after 2 seconds
setTimeout(() => controller.abort(), 2000);
try {
await sleepPromise;
console.log('Sleep completed');
} catch (error) {
console.log('Sleep was cancelled:', error.message); // "Aborted"
}
Automatic Cancellation in Resilient Functions
When used inside a function wrapped with withResilience and useAbortSignal: true, sleep automatically inherits the abort signal:
import { withResilience, sleep } from '@oldwhisper/resilience';
const processWithDelay = withResilience(
async (data: any[]) => {
console.log('Starting processing...');
// This sleep will be automatically cancelled if the function times out
await sleep(2000); // No need to pass signal explicitly!
console.log('Processing after delay...');
return data.map(item => transform(item));
},
{
timeoutMs: 3000,
useAbortSignal: true // Enable automatic abort signal
}
);
// If processing takes longer than 3s, sleep is automatically cancelled
try {
await processWithDelay(largeDataset);
} catch (error) {
console.log('Timed out:', error.message); // "TimeoutError"
}
Polling with Cancellable Sleep
const pollUntilReady = withResilience(
async (resourceId: string) => {
while (true) {
const status = await checkStatus(resourceId);
if (status === 'ready') {
return status;
}
// Sleep between polls, will be cancelled on timeout
await sleep(1000);
}
},
{
timeoutMs: 30000, // 30 second timeout
useAbortSignal: true
}
);
Multi-step Process with Sleep
const multiStepProcess = withResilience(
async () => {
console.log('Step 1: Initialize');
await sleep(500);
console.log('Step 2: Process');
await sleep(1000);
console.log('Step 3: Finalize');
await sleep(500);
return 'Complete';
},
{
retries: 2,
timeoutMs: 5000,
useAbortSignal: true
}
);
// All sleep calls will be cancelled if any step times out
try {
await multiStepProcess();
} catch (error) {
// Handle timeout or other errors
}
Rate Limiting with Sleep
const rateLimitedFetch = withResilience(
async (urls: string[]) => {
const results = [];
for (const url of urls) {
const response = await fetch(url);
results.push(await response.json());
// Wait between requests, respects timeout
await sleep(100);
}
return results;
},
{
timeoutMs: 10000,
useAbortSignal: true
}
);
Error Handling
try {
await sleep(5000, signal);
console.log('Sleep completed normally');
} catch (error) {
if (error.message === 'Aborted') {
console.log('Sleep was cancelled');
} else {
console.log('Unexpected error:', error);
}
}
Integration with Active Signal Context
The sleep function automatically uses the active signal from the current execution context when useAbortSignal is enabled in withResilience:
- When
withResilience creates an AbortController, it sets the active signal
sleep (and resilientFetch) automatically use this signal
- When the timeout expires, the controller aborts, cancelling all pending operations
- The active signal is restored after execution completes
This means you don’t need to manually pass abort signals through your call chain - they’re automatically propagated to all resilient utilities.
Use Cases
- Polling: Wait between status checks with automatic timeout
- Rate Limiting: Add delays between API calls
- Retry Delays: Custom backoff logic using sleep
- Multi-step Workflows: Add pauses between processing steps
- Testing: Simulate delays in test scenarios
- Debouncing: Implement debounce logic with cancellable delays