The problem
Need to timeout promises that take too long to resolve
The solution
function promiseWithTimeout(promise, timeoutMs, timeoutError = 'Promise timeout') {
let timeoutId;
const timeoutPromise = new Promise((_, reject) => {
timeoutId = setTimeout(() => {
reject(new Error(timeoutError));
}, timeoutMs);
});
return Promise.race([promise, timeoutPromise])
.finally(() => {
clearTimeout(timeoutId);
});
}
// Alternative: With AbortController for fetch
async function fetchWithAbortTimeout(url, options = {}, timeoutMs = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, {
...options,
signal: controller.signal
});
clearTimeout(timeoutId);
return response;
} catch (error) {
clearTimeout(timeoutId);
if (error.name === 'AbortError') {
throw new Error(`Request timed out after ${timeoutMs}ms`);
}
throw error;
}
}Parameters
promisePromisePromise to add timeout to
timeoutMsnumberTimeout in milliseconds
timeoutErrorstringError message for timeout
Put it to work
// Basic promise timeout
const slowPromise = new Promise(resolve => {
setTimeout(() => resolve('Done!'), 3000);
});
promiseWithTimeout(slowPromise, 2000, 'Too slow!')
.then(result => console.log(result))
.catch(error => console.error(error)); // Error: Too slow!
// Fetch with timeout
try {
const response = await fetchWithAbortTimeout(
'https://api.example.com/data',
{ method: 'GET' },
3000
);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Request failed:', error.message);
}