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

W tym artykule opisano niektóre metody obsługi błędów podczas korzystania z interfejsu Fetch API. Interfejs Fetch API pozwala wysłać żądanie do zasobu sieci zdalnej. Gdy wykonujesz zdalne połączenie sieciowe, na Twojej stronie internetowej mogą wystąpić różne błędy.

W kolejnych sekcjach opisujemy potencjalne błędy oraz sposoby pisania kodu zapewniającego rozsądny poziom funkcjonalności odporny na błędy i nieoczekiwane warunki sieciowe. Odporny kod dba o zadowolenie użytkowników i utrzymuje standardowy poziom obsługi witryny.

Przewiduj potencjalne błędy sieci

Ta sekcja opisuje scenariusz, w którym użytkownik tworzy nowy film o nazwie "My Travels.mp4", a potem próbuje go przesłać do witryny udostępniania filmów.

Podczas korzystania z narzędzia Fetch można łatwo wybrać szczęśliwą ścieżkę, z której użytkownik pomyślnie prześle film. Istnieją jednak inne ścieżki, które nie są tak płynne, ale wymagają planowania. Takie (nieszczęśliwe) ścieżki mogą pojawić się w wyniku błędu użytkownika, nieoczekiwanych warunków środowiskowych lub błędu w witrynie udostępniania filmów.

Przykłady błędów dotyczących użytkowników

  • Użytkownik przesyła plik graficzny (np. JPEG) zamiast filmu.
  • Użytkownik zaczyna przesyłać nieprawidłowy plik wideo. Następnie w trakcie przesyłania użytkownik wybiera właściwy plik wideo.
  • Użytkownik przypadkowo klika „Anuluj przesyłanie” podczas przesyłania filmu.

Przykłady zmian środowiskowych

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

Przykłady błędów związanych z witryną do udostępniania filmów

  • Witryna do udostępniania filmów nie obsługuje nazwy pliku ze spacją. Zamiast "My Travels.mp4" oczekuje ona nazwy takiej jak "My_Travels.mp4" lub "MyTravels.mp4".
  • Witryna udostępniania filmów wideo nie może przesłać filmów wideo o rozmiarze przekraczającym maksymalny dopuszczalny rozmiar.
  • Witryna do udostępniania filmów nie obsługuje kodeka zawartego w przesłanym filmie.

Takie przykłady mogą i mogą pojawiać się w praktyce. Być może udało Ci się już natrafić na takie przykłady. Wybierzmy po jednym przykładzie z każdej z poprzednich kategorii i omówmy następujące kwestie:

  • Jakie jest domyślne działanie, jeśli usługa udostępniania filmów nie obsługuje danego przykładu?
  • Co użytkownik oczekuje w przykładzie?
  • Jak możemy ulepszyć ten proces?
Działanie Użytkownik zaczyna przesyłać nieprawidłowy plik wideo. Następnie w trakcie przesyłania użytkownik wybiera właściwy plik wideo.
Co dzieje się domyślnie Oryginalny plik będzie nadal przesyłany w tle, a nowy plik będzie przesyłany w tym samym czasie.
czego użytkownik oczekuje, Użytkownik oczekuje, że pierwotne przesyłanie zostanie zatrzymane, co pozwoli uniknąć dodatkowej przepustowości łącza internetowego.
Co można poprawić JavaScript anuluje żądanie pobrania oryginalnego pliku przed rozpoczęciem przesyłania nowego.
Działanie W trakcie przesyłania filmu użytkownik traci połączenie z internetem.
Co dzieje się domyślnie Wygląda na to, że pasek postępu przesyłania zawiesił się na 50%. W końcu interfejs Fetch API przekracza limit czasu i przesłane dane są odrzucane. Po przywróceniu połączenia z internetem użytkownik musi ponownie przesłać plik.
czego użytkownik oczekuje, Użytkownik oczekuje, że zostanie powiadomiony, gdy jego plik nie będzie mógł zostać przesłany, i spodziewa się, że przesyłanie pliku zostanie automatycznie wznowione przy 50% naładowania, gdy znów będzie online.
Co można poprawić Strona przesyłania informuje użytkownika o problemach z połączeniem internetowym oraz zapewnia, że przesyłanie zostanie wznowione po przywróceniu połączenia z internetem.
Działanie Witryna do udostępniania filmów nie obsługuje nazwy pliku ze spacją. Zamiast pliku „Moje podróże.mp4” oczekuje się nazw takich jak „Moje_Podróże.mp4” czy „MojePodróże.mp4”.
Co dzieje się domyślnie Użytkownik musi poczekać na zakończenie przesyłania. Gdy prześlesz plik, a na pasku postępu pojawi się komunikat „100%”, na pasku postępu pojawi się komunikat: „Spróbuj ponownie”.
czego użytkownik oczekuje, Użytkownik spodziewa się, że zostanie powiadomiony o ograniczeniach dotyczących nazw plików przed rozpoczęciem przesyłania lub co najmniej w ciągu 1 sekundy od jego przesłania.
Co można poprawić W idealny sposób usługa udostępniania filmów obsługuje nazwy plików ze spacjami. Możesz też powiadomić użytkownika o ograniczeniach dotyczących nazw pliku przed rozpoczęciem przesyłania. Albo usługa udostępniania filmów powinna odrzucić przesyłanie, podając szczegółowy komunikat o błędzie.

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

Zwróć uwagę, że w tych przykładach kodu jest używany await najwyższego poziomu (obsługa przeglądarek), ponieważ ta funkcja może uprościć kod.

Kiedy interfejs Fetch API zwraca błędy

W tym przykładzie zastosowano instrukcję bloku try/catch do wychwytywania błędów zgłaszanych w bloku try. Jeśli na przykład interfejs Fetch API nie może pobrać określonego zasobu, zgłaszany jest błąd. W takim bloku catch zadbaj o przydatne dla użytkowników. Jeśli użytkownik zobaczy wskaźnik postępu, czyli typowy interfejs pokazujący postęp, możesz wykonać w obrębie bloku catch te działania:

  1. Usuń wskaźnik postępu ze strony.
  2. Przekazuj użytkownikom przydatne informacje, które wyjaśniają, co poszło nie tak i jakie opcje może podjąć użytkownik.
  3. Wyświetl użytkownikowi przycisk „Spróbuj ponownie”, wykorzystując dostępne opcje.
  4. W sposób niewidoczny prześlij szczegóły błędu do usługi śledzenia błędów lub do zaplecza. To działanie spowoduje zarejestrowanie błędu, co pozwoli zdiagnozować go na późniejszym etapie.
try {
  const response = await fetch('https://website');
} catch (error) {
  // TypeError: Failed to fetch
  console.log('There was an error', error);
}

Na późniejszym etapie, podczas zdiagnozowania zgłoszonego błędu, możesz napisać przypadek testowy, aby wychwycić taki błąd, zanim użytkownicy dowiedzą się, że coś jest nie w porządku. W zależności od błędu może to być test jednostkowy, integracja lub akceptacja.

Gdy kod stanu sieci oznacza błąd

Ten przykładowy kod wysyła żądanie do usługi testowej HTTP, która zawsze odpowiada kodem stanu HTTP 429 Too Many Requests. Co ciekawe, odpowiedź nie dociera do bloku catch. Stan 404, wraz z innymi kodami stanu, nie zwraca błędu sieci, ale rozwiązuje problem normalnie.

Aby sprawdzić, czy kod stanu HTTP zakończył się powodzeniem, możesz skorzystać z dowolnej z tych opcji:

  • Użyj właściwości Response.ok, aby ustalić, czy kod stanu mieścił się w zakresie od 200 do 299.
  • Użyj właściwości Response.status, aby sprawdzić, czy odpowiedź zakończyła się powodzeniem.
  • Użyj innych metadanych, np. Response.headers, aby ocenić, czy odpowiedź zakończyła się powodzeniem.
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}`)
}

Najlepiej współpracować z osobami w organizacji i zespole, aby zrozumieć potencjalne kody stanu odpowiedzi HTTP. Programiści backendu, programiści i inżynierowie usług mogą czasem dostarczyć wyjątkowe informacje o możliwych przypadkach skrajnych, których możesz nie przewidzieć.

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

W tym przykładzie kodu pokazujemy inny typ błędu, który może się pojawić podczas analizowania treści odpowiedzi. Interfejs Response udostępnia wygodne metody analizowania różnych typów danych, takich jak tekst czy dane JSON. W poniższym kodzie żądanie sieciowe jest wysyłane do usługi testowej HTTP, która zwraca ciąg znaków HTML jako treść odpowiedzi. Podejmowana jest jednak próba przeanalizowania treści odpowiedzi jako JSON, co spowoduje 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ć swój kod pod kątem stosowania różnych formatów odpowiedzi i upewnić się, że nieoczekiwana odpowiedź nie zakłóca użytkownikowi strony internetowej.

Rozważ zastosowanie następującego scenariusza: masz zasób zdalny, który zwraca prawidłową odpowiedź JSON, która została prawidłowo przeanalizowana za pomocą metody Response.json(). Może się zdarzyć, że usługa nie będzie działać. Gdy funkcja jest wyłączona, zwracany jest element 500 Internal Server Error. Jeśli podczas analizy kodu JSON nie są stosowane odpowiednie techniki obsługi błędów, może to uszkodzić stronę dla użytkownika z powodu wystąpienia nieobsłużonego błędu.

Gdy żądanie sieciowe musi zostać anulowane przed zakończeniem

W tym przykładowym kodzie używany jest element AbortController do anulowania żądania przesyłanego w trakcie przesyłania. Żądanie przesyłane to żądanie sieciowe, które już się rozpoczęło, ale nie zostało ukończone.

Anulowanie żądania w trakcie przesyłania może się różnić, ale ostatecznie zależy od konkretnego przypadku użycia i środowiska. Poniższy kod pokazuje, jak przesłać AbortSignal do interfejsu Fetch API. Element AbortSignal jest dołączony do AbortController, a AbortController zawiera metodę abort(), która informuje przeglądarkę, że żądanie sieciowe 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

Ważnym aspektem obsługi błędów jest wskazanie poszczególnych elementów, które mogą pójść nie tak. W każdej sytuacji zadbaj o odpowiednie działanie kreacji zastępczej dla użytkownika. Jeśli chodzi o żądanie pobierania, zadaj sobie takie pytania:

  • Co się stanie, jeśli serwer docelowy ulegnie awarii?
  • Co się stanie, gdy funkcja Fetch otrzyma nieoczekiwaną odpowiedź?
  • Co się stanie, jeśli użytkownik utraci połączenie z internetem?

W zależności od złożoności strony internetowej możesz też narysować schemat blokowy opisujący funkcje i interfejs użytkownika dla różnych scenariuszy.