Таймаут для fetch обычно собирают из трёх частей: AbortController, setTimeout, который дёргает abort(), и clearTimeout в finally.
try {
const res = await fetch(url, {
signal: AbortSignal.timeout(5000)
});
const data = await res.json();
} catch (err) {
if (err.name === 'TimeoutError') {
// ответа нет 5 секунд
}
}AbortSignal.timeout(5000) создаёт сигнал, который сам сработает через 5 секунд. Передаёшь его в fetch как обычный signal, таймер живёт внутри сигнала, чистить его в finally не нужно. Ошибка приходит с именем TimeoutError, а не AbortError — по нему в catch отличаешь «сервер не ответил» от «пользователь отменил».
Таймер не останавливается после первого await. Если сервер прислал заголовки, а тело отдаёт по капле, то res.json() тоже упадёт с TimeoutError, когда 5 секунд истекут. Отдельный таймаут на чтение ответа ставить не нужно.
Работает в Chrome с 124-й версии, Firefox со 100-й, Safari с 16-й.
🔥 — если было полезно
@glo_academy | #js_day