Comment continuer catchError dans timer (rxjs)

Aug 23 2020

J'ai un service qui est chargé d'exécuter un httpClient.get toutes les x secondes, en utilisant une minuterie. J'ai besoin de cette minuterie pour commencer à fonctionner chaque fois que le service est actif, de sorte que la minuterie est définie dans le constructeur de service . Selon ma compréhension, l'abonnement doit être enregistré dans la portée de la minuterie comme indiqué ci-dessous (je ne veux pas le changer s'il n'est pas nécessaire, sauf si c'est incorrect).

Le système tout fonctionne correctement tant qu'il n'y a pas d'exception d'erreur \ exceptions \ erreur 500 du serveur principal. Maintenant, j'ai besoin de 2 choses:

  1. Je voudrais catchError chaque fois qu'il y a un problème dans le serveur principal.
  2. Je voudrais que l'observateur continue de fonctionner en fonction des temps de la minuterie (jusqu'au prochain tick), même s'il y a une exception. Mon résultat final devrait atteindre le popUpAlert dans le composant chaque fois qu'il y a une exception Voir mon code - c'est le contrôleur webapi:
public IActionResult getSomeErrorAsTest()
{
    try
    {
        throw new Exception("Serer error");
    }
    catch(Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError, new List<string>());
        //throw ex;
    }
}

Ceci est le service (supposons que les données changent à chaque requête get - pas besoin de l'implémenter si c'est vraiment le cas):

export class MyService
{
    MyDataSubject = new Subject<any[]>();
    MyDataChanged :Observable>any[]> = this.MyDataSubject.asObservable();
    
    subscribe :Subscription;
    constructor(private httpClient : HttpClient)
    {
        this.subscribe = timer(0, 30000).pipe(
        switchMap(()=>
            this.getData())).subscribe();
    }
    getData()
    {
        return this.httpClient.get<any[]>(<controller url>)
        .pipe(
            tap(res =>
            {
                this.MyDataSubject.next(res);
            }),
            catchError(error =>
                {
                    debugger;//I would expect to catch the debugger here, but nothing happens
                    return throwError(error);
                })
            )
    }
}   

Le composant consommateur:

export class MyComponent (private mySrv : MyService)
{
    getMyData()
    {
        let sub =this.mySrv.MyDataChanged.subscribe(result => doSomething(),
                                                    error=> popUpAlert());
    }
}

Réponses

2 RafiHenig Aug 23 2020 at 18:42

CatchErrorL'opérateur permet de gérer l'erreur, mais ne change pas la nature de l'observable - l'erreur est une condition terminale en un observable donné, donc l'émission s'arrêtera. CatchErrorpermet d'émettre la valeur des désirs quand cela se produit au lieu de lever le rappel d'erreur de l'observateur ( métasong ).

Vous voudrez peut-être gérer les erreurs dans Observable interne (c'est-à-dire à l'intérieur switchMap), de sorte que les erreurs générées à cet endroit ne remonteront pas dans le flux principal, de cette façon, le flux principal continue après une erreur, comme illustré ci-dessous:

  this.subscribe = timer(0, 30000)
    .pipe(
      switchMap(() => this.getData().pipe(catchError(x => of("handle error here"))))
      // catchError(...) don't handle error here
    )
    .subscribe();