await-timeout
await-timeout, currently at version 1.1.1, offers a Promise-based API for handling `setTimeout` and `clearTimeout` in JavaScript, making it particularly useful within `async/await` constructs. It simplifies common asynchronous patterns such as adding timeouts to network requests or other long-running operations. The library provides both static methods like `Timeout.set(ms)` for simple delays and instance methods (`new Timeout().set(ms)`) for more controlled scenarios, including wrapping existing promises with timeouts using `Timeout.wrap(promise, ms, rejectReason)`. A key differentiator is its emphasis on proper resource management, advising the use of `.clear()` within `finally` blocks to prevent unhandled promise rejections or 'unexpected effects' when dealing with `Promise.race`. While a specific release cadence isn't detailed, its stable 1.x version implies a mature and focused utility for precise timeout management in asynchronous codebases.
Common errors
-
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: X): Error: Timeout!
cause A `Timeout.set(ms, 'Timeout!')` promise was rejected, but there was no `.catch()` handler or surrounding `try...catch` block to manage it.fixAdd a `.catch()` block to the promise returned by `Timeout.set()` or wrap the `await Timeout.set()` call in a `try...catch` statement to handle the rejection. -
TypeError: Timeout is not a constructor
cause Attempting to call `Timeout()` directly without the `new` keyword, or incorrect import of the default export.fixUse `const timer = new Timeout();` to create an instance, ensuring `Timeout` is correctly imported as a class: `import Timeout from 'await-timeout';`.
Warnings
- gotcha When using `Timeout` instances, especially with `Promise.race`, it is crucial to always call `.clear()` in a `finally` block. Failing to do so can lead to 'unexpected effects' or unhandled promise rejections, as the internal `setTimeout` might still fire even if the race condition is met by another promise.
- gotcha If `Timeout.set(delay, rejectReason)` is used to create a rejecting promise and that promise is not caught or handled, it will result in an 'Unhandled Promise Rejection' error in Node.js or the browser console.
- gotcha The `Timeout.wrap(promise, delay, rejectReason)` static method is a convenient shortcut, but it internally creates and manages a `Timeout` instance. While it handles clearing the timer automatically, developers should understand its behavior to avoid misuse or misinterpreting its interactions in complex promise chains.
Install
-
npm install await-timeout -
yarn add await-timeout -
pnpm add await-timeout
Imports
- Timeout
const Timeout = require('await-timeout');import Timeout from 'await-timeout';
- Timeout.set (static)
await new Timeout().set(1000);
await Timeout.set(1000);
- Timeout (instance)
const timer = Timeout();
const timer = new Timeout();
Quickstart
import Timeout from 'await-timeout';
async function fetchWithTimeoutExample() {
const timer = new Timeout();
try {
console.log('Attempting to fetch data with a 1-second timeout...');
const dataPromise = fetch('https://jsonplaceholder.typicode.com/todos/1').then(res => res.json());
const result = await Promise.race([
dataPromise,
timer.set(1000, new Error('Fetch operation timed out!')) // Rejects after 1 second
]);
if (result instanceof Error) {
throw result; // Propagate the timeout error
}
console.log('Data fetched successfully:', result.title);
} catch (error) {
console.error('Operation failed:', error.message);
} finally {
timer.clear(); // Essential cleanup to prevent resource leaks and 'unexpected effects'
console.log('Timeout timer cleared.');
}
}
async function simpleDelayExample() {
console.log('\nStarting a 500ms delay...');
await Timeout.set(500); // Static method for a simple awaitable delay
console.log('Delay finished after 500ms.');
}
fetchWithTimeoutExample();
simpleDelayExample();