angulartimerrxjsrxjs-observablesrxjs-pipe

How to continue catchError in timer (rxjs)


I have a service that is responsible to execute a httpClient.get every x seconds, using a timer. I need this timer to start running whenever the service is up, so the timer is defined in the service constructor. According to my understanding, the subscription should be registered in the timer scope as seen below (I don't want to change it if there's no need, unless it is incorrect).

The all system is working fine as long as there are no errors\exceptions\error 500 exception from the backend server. Now, I need 2 things:

  1. I would like to catchError whenever there is a problem in the backend server.
  2. I would like the observer to keep running according to the timer times (to the next tick), even if there is an exception. My final result should be reaching the popUpAlert in the component whenever there is exception See my code - this the webapi controller:
public IActionResult getSomeErrorAsTest()
{
    try
    {
        throw new Exception("Serer error");
    }
    catch(Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError, new List<string>());
        //throw ex;
    }
}

This is the service (assume that the data changes in every get request - no need to implement if it really do):

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

The consumer component:

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

Solution

  • CatchError operator allows to handle error, but doesn't change nature of observable - error is terminal condition to given observable so emission will stop. CatchError allows to emit desires value when it occurs instead of raising observer's error callback (metasong). enter image description here

    You might want to handle errors in inner Observable (i.e. inside switchMap), so errors thrown there, will not bubble up to main stream, that way the main stream continues after an error occurs, as demonstrated below:

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