Definiowanie timeoutów z Fetch API

  • javascript

Obecnie definiowanie timeoutów jest bardzo proste. Wystarczy wywołać metodę statyczną AbortSignal.timeout(), która zwraca signal, który natomiast przekazujemy do fetch.

const response = await fetch(url, {
    signal: AbortSignal.timeout(2000) // 2 sekundy
});

Obsługa wyjątków

Gdy odpowiedź z serwera będzie dłuższa niż zdefiniowany timeout, fetch rzuci wyjątkiem TimeoutError.

try {
    await fetch(url, {
    signal: AbortSignal.timeout(2000) // 2 sekundy
    });
} catch (err) {
    if (err.name === 'TimeoutError') {
        // tutaj możesz obsłużyć wyjątek
    }
}

Wsparcie przeglądarek

AbortSignal: timeout() w 2025 ma dość solidne wsparcie. Funkcjonalność na dzień pisania artykułu obsługiwana jest przez ~93% wersji przeglądarek.

Alternatywne podejście

AbortController: abort() pozwala przerwać request z dowolnego powodu. Jako że artykuł skupia się na timeoutach to pokażę Ci, jak również go obsłużyć za pomocą tej metody.

const abortController = new AbortController()
const timeoutId = setTimeout(
    () => abortController.abort(),
    2000, // 2 sekundy
)
try {
    await fetch(url, { signal: abortController.signal })
    clearTimeout(timeoutId)
} catch (err) {
    if (err.name === 'AbortError') {
        // tutaj możesz obsłużyć wyjątek
    }
}

Jak wspomniałem, możesz użyć .abort() dla dowolnego powodu. Na przykład, aby anulować zapytanie HTTP po kliknięciu przycisku:

const button = document.querySelector('button')
const abortController = new AbortController()
button.onclick = () => abortController.abort() // `addEventListener` jest lepszy, ale `onclick` jest krótszy do celów prezentacji.
try {
    fetch(url, { signal: abortController.signal }) // `await` jest pominięty celowo
    button.click()
} catch (err) {
    if (err.name === 'AbortError') {
        // tutaj możesz obsłużyć wyjątek
    }
}

Bibliografia