Come continuare a catchError nel timer (rxjs)

Aug 23 2020

Ho un servizio che è responsabile di eseguire un httpClient.get ogni x secondi, utilizzando un timer. Ho bisogno che questo timer inizi a funzionare ogni volta che il servizio è attivo, quindi il timer è definito nel costruttore del servizio . Secondo la mia comprensione, l'abbonamento dovrebbe essere registrato nell'ambito del timer come mostrato di seguito (non voglio cambiarlo se non è necessario, a meno che non sia errato).

Tutto il sistema funziona correttamente fintanto che non ci sono errori \ eccezioni \ eccezioni errore 500 dal server di backend. Ora, ho bisogno di 2 cose:

  1. Vorrei catchError ogni volta che c'è un problema nel server di backend.
  2. Vorrei che l'osservatore continuasse a funzionare in base ai tempi del timer (al tick successivo), anche se c'è un'eccezione. Il mio risultato finale dovrebbe raggiungere il popUpAlert nel componente ogni volta che c'è un'eccezione Vedi il mio codice - questo è il controller webapi:
public IActionResult getSomeErrorAsTest()
{
    try
    {
        throw new Exception("Serer error");
    }
    catch(Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError, new List<string>());
        //throw ex;
    }
}

Questo è il servizio (supponi che i dati cambino in ogni richiesta get - non è necessario implementarlo se lo fa davvero):

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);
                })
            )
    }
}   

La componente consumatore:

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

Risposte

2 RafiHenig Aug 23 2020 at 18:42

CatchErrorL'operatore consente di gestire l'errore, ma non cambia la natura dell'osservabile: l'errore è la condizione terminale per un dato osservabile, quindi l'emissione si fermerà. CatchErrorpermette di emettere il valore dei desideri quando si verifica invece di aumentare il callback dell'errore dell'osservatore ( metasong ).

Potresti voler gestire gli errori nell'Observable interno (cioè all'interno switchMap), in modo che gli errori generati lì non si diffondano nel flusso principale, in questo modo il flusso principale continua dopo che si è verificato un errore, come mostrato di seguito:

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