Implementacja obsługi błędów w przypadku korzystania z interfejsu Fetch API

Z tego artykułu dowiesz się, jak radzić sobie z błędami podczas korzystania z interfejsu Fetch API. Interfejs Fetch API umożliwia wysyłanie żądań do zdalnego zasobu sieciowego. Gdy wysyłasz wywołanie sieci zdalnej, Twoja strona internetowa może być narażona na różne potencjalne błędy sieciowe.

W następnych sekcjach opisujemy potencjalne błędy i podajemy wskazówki, jak pisać kod, który zapewnia odpowiedni poziom funkcjonalności i jest odporny na błędy oraz nieoczekiwane warunki sieciowe. Dzięki elastycznemu kodowi użytkownicy są zadowoleni, a Twoja witryna zachowuje standardowy poziom usług.

Zapobieganie potencjalnym błędom sieci

W tej sekcji opisujemy scenariusz, w którym użytkownik tworzy nowy film o nazwie "My Travels.mp4", a następnie próbuje przesłać go na stronę do udostępniania filmów.

Podczas pracy z Fetch łatwo jest wziąć pod uwagę sytuację idealną, w której użytkownik przesyła film. Istnieją jednak inne ścieżki, które nie są tak płynne, ale twórcy stron internetowych muszą je uwzględnić w planowaniu. Takie (nieszczęśliwe) ścieżki mogą być spowodowane błędem użytkownika, nieoczekiwanymi warunkami środowiskowymi lub błędem w witrynie do udostępniania filmów.

Przykłady błędów popełnianych przez użytkowników

  • Użytkownik przesyła plik obrazu (np. JPEG) zamiast pliku wideo.
  • Użytkownik zaczyna przesyłać niewłaściwy plik wideo. Następnie, w połowie przesyłania, użytkownik wskazuje odpowiedni plik wideo do przesłania.
  • Użytkownik przypadkowo klika „Anuluj przesyłanie” podczas przesyłania filmu.

Przykłady zmian środowiskowych

  • połączenie z internetem zostanie utracone podczas przesyłania filmu.
  • Podczas przesyłania filmu przeglądarka się ponownie uruchamia.
  • Serwery witryny do udostępniania filmów są ponownie uruchamiane podczas przesyłania filmu.

Przykłady błędów w witrynie do udostępniania filmów

  • Witryna do udostępniania filmów nie obsługuje nazw plików ze spacją. Zamiast "My Travels.mp4" oczekuje nazwy takiej jak "My_Travels.mp4" lub "MyTravels.mp4".
  • Witryna do udostępniania filmów nie może przesłać filmu, którego rozmiar przekracza maksymalny dopuszczalny rozmiar pliku.
  • Witryna do udostępniania filmów nie obsługuje kodeka wideo w przesłanym filmie.

Te przykłady mogą się zdarzyć w rzeczywistych sytuacjach. Być może już je znasz. Wybierzmy po jednym przykładzie z każdej z tych kategorii i omówimy te kwestie:

  • Jakie jest domyślne działanie, jeśli usługa do udostępniania filmów nie może obsłużyć danego przykładu?
  • Czego użytkownik oczekuje w tym przykładzie?
  • Jak możemy ulepszyć ten proces?
Działanie Użytkownik zaczyna przesyłać niewłaściwy plik wideo. Następnie, w połowie przesyłania, użytkownik wskazuje odpowiedni plik wideo do przesłania.
Co się dzieje domyślnie Oryginalny plik nadal jest przesyłany w tle, a nowy plik jest przesyłany w tym samym czasie.
Czego oczekuje użytkownik Użytkownik oczekuje, że pierwotne przesyłanie zostanie zatrzymane, aby nie marnować dodatkowej przepustowości internetu.
Co można poprawić Kod JavaScript anuluje żądanie pobierania oryginalnego pliku, zanim rozpocznie się przesyłanie nowego pliku.
Działanie Użytkownik traci połączenie z internetem w trakcie przesyłania filmu.
Co się dzieje domyślnie Pasek postępu przesyłania zatrzymał się na 50%. W końcu interfejs Fetch API osiąga limit czasu, a przesłane dane są odrzucane. Gdy połączenie z internetem zostanie przywrócone, użytkownik musi ponownie przesłać plik.
Czego oczekuje użytkownik Użytkownik oczekuje powiadomienia, gdy nie może przesłać pliku, i oczekuje, że przesyłanie zostanie automatycznie wznowione na poziomie 50%, gdy wróci do sieci.
Co można poprawić Strona przesyłania informuje użytkownika o problemach z połączeniem z internetem i zapewnia, że przesyłanie zostanie wznowione, gdy połączenie z internetem zostanie przywrócone.
Działanie Witryna do udostępniania filmów nie obsługuje nazw plików ze spacją. Zamiast „Moje podróże.mp4” oczekuje nazw takich jak „Moje_podróże.mp4” lub „MojePodróże.mp4”.
Co się dzieje domyślnie Użytkownik musi zaczekać na zakończenie przesyłania. Gdy plik zostanie przesłany, a pasek postępu osiągnie wartość „100%”, pojawi się komunikat „Spróbuj ponownie”.
Czego oczekuje użytkownik Użytkownik powinien zostać poinformowany o ograniczeniach dotyczących nazw plików przed rozpoczęciem przesyłania lub co najmniej w pierwszej sekundzie przesyłania.
Co można poprawić W idealnej sytuacji usługa udostępniania filmów powinna obsługiwać nazwy plików ze spacjami. Alternatywą jest powiadomienie użytkownika o ograniczeniach dotyczących nazwy pliku przed rozpoczęciem przesyłania. Usługa udostępniania filmów powinna odrzucić przesłanie, wyświetlając szczegółowy komunikat o błędzie.

Obsługa błędów za pomocą interfejsu Fetch API

Pamiętaj, że poniższe przykłady kodu używają poziomu najwyższego await (obsługa w przeglądarce), ponieważ ta funkcja może uprościć kod.

Gdy interfejs Fetch API zwraca błędy

W tym przykładzie użyto instrukcji try/catch, aby przechwytywać błędy zgłaszane w bloku try. Jeśli na przykład interfejs Fetch API nie może pobrać określonego zasobu, zostanie wygenerowany błąd. W bloku catch takiego jak ten zadbaj o dobre wrażenia użytkowników. Jeśli użytkownikowi wyświetla się spinner, czyli element interfejsu użytkownika przedstawiający postęp, możesz wykonać w bloku catch te czynności:

  1. Usuń spinner ze strony.
  2. wyświetlić przydatne komunikaty wyjaśniające, co poszło nie tak, i jakie opcje ma użytkownik;
  3. Na podstawie dostępnych opcji wyświetl użytkownikowi przycisk „Spróbuj ponownie”.
  4. W tle wyślij szczegóły błędu do usługi śledzenia błędów lub do backendu. To działanie rejestruje błąd, aby można było go zdiagnozować na późniejszym etapie.
try {
 
const response = await fetch('https://website');
} catch (error) {
 
// TypeError: Failed to fetch
  console
.log('There was an error', error);
}

Później, podczas diagnozowania zarejestrowanego błędu, możesz napisać przypadek testowy, aby wykrywać takie błędy, zanim użytkownicy zauważą, że coś jest nie tak. W zależności od błędu test może być testem jednostkowym, testem integracji lub testem akceptacyjnym.

Gdy kod stanu sieci oznacza błąd

Ten przykład kodu wysyła żądanie do usługi testowania HTTP, która zawsze odpowiada kodem stanu HTTP 429 Too Many Requests. Co ciekawe, odpowiedź nie dociera do bloku catch. Stan 404, podobnie jak niektóre inne kody stanu, nie zwraca błędu sieci, ale jest normalnie rozwiązywany.

Aby sprawdzić, czy kod stanu HTTP jest prawidłowy, możesz użyć jednej z tych opcji:

  • Użyj właściwości Response.ok, aby określić, czy kod stanu mieścił się w zakresie od 200 do 299.
  • Aby sprawdzić, czy odpowiedź została wysłana, użyj właściwości Response.status.
  • Aby ocenić, czy odpowiedź była prawidłowa, użyj dowolnych innych metadanych, np. Response.headers.
let response;

try {
  response
= await fetch('https://httpbin.org/status/429');
} catch (error) {
  console
.log('There was an error', error);
}

// Uses the 'optional chaining' operator
if (response?.ok) {
  console
.log('Use the response here!');
} else {
  console
.log(`HTTP Response Code: ${response?.status}`)
}

Najlepszym sposobem na poznanie możliwych kodów stanu odpowiedzi HTTP jest współpraca z osobami z Twojej organizacji i zespołu. Deweloperzy backendu, specjaliści ds. operacji deweloperskich i inżynierowie serwisu mogą czasami dostarczyć unikalnych informacji o możliwych przypadkach skrajnych, których nie da się przewidzieć.

Gdy wystąpi błąd podczas analizowania odpowiedzi sieci

Ten przykład kodu pokazuje inny typ błędu, który może wystąpić podczas analizowania treści odpowiedzi. Interfejs Response oferuje wygodne metody analizowania różnych typów danych, np. tekstu lub JSON. W tym kodzie wysyłane jest żądanie sieciowe do usługi testowania HTTP, która zwraca ciąg tekstowy HTML jako treść odpowiedzi. Jednak próba przeanalizowania treści odpowiedzi jako JSON powoduje błąd.

let json;

try {
 
const response = await fetch('https://httpbin.org/html');
  json
= await response.json();
} catch (error) {
 
if (error instanceof SyntaxError) {
   
// Unexpected token < in JSON
    console
.log('There was a SyntaxError', error);
 
} else {
    console
.log('There was an error', error);
 
}
}

if (json) {
  console
.log('Use the JSON here!', json);
}

Musisz przygotować kod, aby obsługiwał różne formaty odpowiedzi, i sprawdzać, czy nieoczekiwana odpowiedź nie powoduje błędu na stronie internetowej.

Rozważmy taki scenariusz: masz zdalny zasób, który zwraca prawidłową odpowiedź JSON i jest on poprawnie analizowany za pomocą metody Response.json(). Może się zdarzyć, że usługa przestanie działać. Po zakończeniu działania funkcji zwracany jest parametr 500 Internal Server Error. Jeśli podczas analizowania pliku JSON nie zostaną użyte odpowiednie techniki obsługi błędów, może to spowodować nieprawidłowe działanie strony dla użytkownika, ponieważ zostanie wygenerowany nieobsługiwany błąd.

Kiedy żądanie sieci musi zostać anulowane przed zakończeniem

W tym przykładzie kodu użyto elementu AbortController, aby anulować bieżące żądanie. Przesyłane żądanie to żądanie sieciowe, które zostało rozpoczęte, ale nie zostało jeszcze zakończone.

Wymagania anulowania żądania w trakcie realizacji mogą się różnić, ale ostatecznie wszystko zależy od przypadku użycia i środowiska. Poniższy kod pokazuje, jak przekazać parametr AbortSignal do interfejsu Fetch API. Element AbortSignal jest dołączony do elementu AbortController, a element AbortController zawiera metodę abort(), która informuje przeglądarkę, że żądanie sieci powinno zostać anulowane.

const controller = new AbortController();
const signal = controller.signal;

// Cancel the fetch request in 500ms
setTimeout
(() => controller.abort(), 500);

try {
 
const url = 'https://httpbin.org/delay/1';
 
const response = await fetch(url, { signal });
  console
.log(response);
} catch (error) {
 
// DOMException: The user aborted a request.
  console
.log('Error: ', error)
}

Podsumowanie

Jednym z ważnych aspektów obsługi błędów jest określenie różnych elementów, które mogą się nie udać. W każdym scenariuszu upewnij się, że masz odpowiednią opcję zastępczą dla użytkownika. W przypadku żądania pobierania zadaj sobie pytania w rodzaju:

  • Co się stanie, jeśli serwer docelowy przestanie działać?
  • Co się stanie, jeśli Fetch otrzyma nieoczekiwaną odpowiedź?
  • Co się stanie, jeśli połączenie internetowe użytkownika nie będzie działać?

W zależności od złożoności strony możesz też narysować schemat przepływu danych, który opisuje funkcje i interfejs użytkownika w różnych scenariuszach.