Как задать таймаут для fetch
Короткий ответ
fetch() сам по себе ждёт сколько угодно. AbortSignal.timeout() создаёт сигнал, который отменяет запрос через заданное число миллисекунд:
const response = await fetch('/api/report', { signal: AbortSignal.timeout(5000) });Как распознать таймаут
При таймауте ошибка называется TimeoutError, при ручной отмене — AbortError:
try {
const response = await fetch('/api/report', { signal: AbortSignal.timeout(5000) });
const report = await response.json();
} catch (error) {
if (error.name === 'TimeoutError') {
showMessage('The server is taking too long. Try again later.');
} else {
throw error;
}
}Через AbortController
AbortController даёт сигнал, который вы отменяете сами, например кнопкой или по таймеру:
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch('/api/report', { signal: controller.signal });
console.log(await response.json());
} finally {
clearTimeout(timer);
}Как это работает
Любая операция на промисах, которая принимает сигнал, ведёт себя так же. Небольшой пример без сети:
const signal = AbortSignal.timeout(50);
await new Promise((resolve) => setTimeout(resolve, 100));
console.log(signal.aborted, signal.reason.name);Результат:
true TimeoutErrorЧастая ошибка
Один только таймер setTimeout() запрос не останавливает: он продолжает загружаться в фоне. Передайте fetch() сигнал, чтобы запрос действительно отменился.
// the request continues even after the message
setTimeout(() => showMessage('Too slow'), 5000);
const response = await fetch('/api/report');Функции из этого ответа
- fetch — Отправляет HTTP-запрос и возвращает промис ответа.