← Назад к вопросам
Есть ли у Promise функционал для принудительного завершения через 5 секунд?
1.0 Junior🔥 141 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Promise timeout функционал
В стандартном JavaScript Promise нет встроенного функционала для принудительного завершения через определенное время. Однако существует несколько способов реализовать эту функциональность.
1. Использование Promise.race()
Это наиболее элегантный способ - гарантировать выполнение за определенное время:
// Функция для создания таймаута
function timeout(ms) {
return new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms)
);
}
// Использование
const fetchWithTimeout = async () => {
try {
const result = await Promise.race([
fetch('https://api.example.com/data'),
timeout(5000) // 5 секунд
]);
return result;
} catch (error) {
console.error('Операция прервана или истек таймаут:', error);
}
};
2. AbortController (современный способ)
В современном JavaScript есть AbortController, который позволяет отменить fetch запрос:
const fetchWithTimeout = async (url, timeout = 5000) => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
signal: controller.signal
});
clearTimeout(timeoutId);
return response;
} catch (error) {
if (error.name === 'AbortError') {
console.error('Запрос отменен по таймауту');
}
throw error;
}
};
// Использование
await fetchWithTimeout('https://api.example.com/data', 5000);
3. Реализация helper функции
// Универсальная функция для любого Promise
function withTimeout(promise, ms) {
return Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => {
reject(new Error(`Operation timed out after ${ms}ms`));
}, ms)
)
]);
}
// Примеры использования
const slowFetch = fetch('https://api.example.com/data');
try {
const result = await withTimeout(slowFetch, 5000);
console.log('Успешно:', result);
} catch (error) {
console.error('Ошибка или таймаут:', error.message);
}
4. Класс для более удобного использования
class TimeoutError extends Error {
constructor(ms) {
super(`Operation timed out after ${ms}ms`);
this.name = 'TimeoutError';
}
}
class PromiseWithTimeout {
static race(promise, timeout) {
return Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => reject(new TimeoutError(timeout)), timeout)
)
]);
}
static async fetch(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeoutId);
return response;
} catch (error) {
clearTimeout(timeoutId);
throw error;
}
}
}
// Использование
try {
const response = await PromiseWithTimeout.fetch('/api/data', 5000);
} catch (error) {
if (error instanceof TimeoutError) {
console.log('Таймаут истек');
}
}
5. Практический пример в React
import { useState, useEffect } from 'react';
const DataFetcher = () => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
const fetchData = async () => {
try {
const response = await fetch('/api/data', {
signal: controller.signal
});
const result = await response.json();
setData(result);
} catch (err) {
setError(
err.name === 'AbortError'
? 'Запрос превышил таймаут'
: err.message
);
} finally {
setLoading(false);
clearTimeout(timeoutId);
}
};
fetchData();
return () => {
controller.abort();
clearTimeout(timeoutId);
};
}, []);
if (loading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка: {error}</div>;
return <div>{JSON.stringify(data)}</div>;
};
Сравнение подходов
| Подход | Плюсы | Минусы |
|---|---|---|
| Promise.race() | Простой, работает везде | Нужно создавать отдельный Promise |
| AbortController | Современный, отменяет запрос | Работает с fetch/XHR, не всегда поддерживается |
| setTimeout + reject | Универсальный | Более многословный код |
Вывод
Нет встроенной функции в Promise, но есть несколько проверенных способов реализовать таймаут. Рекомендуется использовать AbortController для fetch запросов и Promise.race() для универсальных случаев.