Zarządzanie błędami w strumieniach danych – „retry” w RxJS

RxJS-logo

Strumienie danych i zażądanie nimi to chleb powszedni dla programistów pracujących z Angularem. Z pomocą przychodzi nam tutaj biblioteka RxJS i jej operator „retry” o którym opowiem dzisiaj szerzej w moim wpisie.

Czym jest operator 'retry'?

Operator retry w RxJS pozwala na ponowienie subskrypcji do strumienia, który generuje błąd. Gdy w strumieniu wystąpi błąd, operacja retry automatycznie ponowi subskrypcję do źródła, co może być niezwykle przydatne w przypadku awaryjnych sytuacji, takich jak problemy sieciowe.

Daje nam jeszcze możliwość implementacji dodatkowego kodu, który wykona się przed ponową subskrypcją.

Przykład użycia

Rozważmy prosty przykład, w którym pobieramy dane z serwera za pomocą HttpClient i chcemy ponowić próbę w przypadku wystąpienia błędu.

import {inject, Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {retry, timer} from "rxjs";

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  private httpClient = inject(HttpClient)

  getData() {
    const url = 'google.pl';
    return this.httpClient.get(url).pipe(retry(3));
  }
}

W celach testowych ustawiłem pierwszy lepszy url, który przyszedł mi do głowy. Po implementacji powyższego kodu w konsoli z requestami sieciowymi zobaczymy łącznie cztery próby wykonania się requestu typu get. Cztery próby ponieważ jedna próba jest wykonywana na początku a 3 to ponowienia, które ustawiliśmy w konfiguracji pipa retry. Oczywiście wszystkie zakończą się niepowodzeniem z racji niepoprawnego adresu.

Jeśli chcielibyśmy zaimplementować specyficzną logikę w zależności od np. kodu błędu to jak najbardziej jest taka możliwość. Jak widać na poniższym przykładzie mamy dostęp do obiektu error, który zawiera wszystkie potrzebne informacje:

getData() {
    const url = 'google.pl';
    return this.httpClient.get(url).pipe(retry({
      count: 3, delay: (error, retryCount) => {
        // twój kod
        return timer(1000)
      }
    }));
  }

Co jeśli chciałbym przerwać ponawianie?

Załóżmy, że jest taki przypadek, w którym już nie chcemy próbować ponownie i przestać ponawiać request – jak najbardziej jest taka możliwość, musimy tylko zwrócić observable z błędem jak przykładowo zrobiłem to poniżej:

getData() {
    const url = 'google.pl';
    return this.httpClient.get(url).pipe(retry({
      count: 3, delay: (error, retryCount) => {
        if (retryCount === 2) {
          return throwError(() => error)
        }
        return timer(1000)
      }
    }));
  }

Podsumowanie

Operator „retry” w RxJS jest niezwykle przydatnym narzędziem do zarządzania błędami w strumieniach danych. Pozwala on na automatyczne ponowienie subskrypcji do źródła danych w przypadku wystąpienia błędu oraz dodanie dodatkowej logiki, która być może rozwiąże problem 🙂

Dzięki za przeczytanie i miłego dnia!