Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как задать таймаут для 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-запрос и возвращает промис ответа.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.