Sunday, November 21, 2021

How to retry a subscription when it fails in Angular 9?

 Context: Working with Angular 9. I'm trying to wait the back-end to be available to receive requests. Meanwhile it's not, there is a progress bar loading.

Issue: when the back-end is not yet available, the subscription fails immediately and enters the (error) callback function of the method .subscribe(), with a message like Http failure response for http://localhost:5555/api/info: 504 Gateway Timeout

I did research a bit, and the examples I've found modify the service class where httpClient.get is present, to retry x times the request, but I can't do that as the ts service is auto generated.

My 1st idea was to use while() loop and a flag, so each time (error) was executed, the flag would be false and then retry the subscription. But it would lead to a memory leak.

checkIfBackendAvailable() {
    var backendAvailable = false;
    while(!backendAvailable){
      let subscription = this.infoService.getInfo().subscribe(
      (info) => {
        if (info) {
            backendAvailable = true;
            this.progressBarValue = 100
            // do somethings
         }
       }
        ,
        (error) => {
          clearTimeout(this.infoTimeOut);
          this.showMessage("back-end not available");
          this.stopLoadingBar();
          //do somethings
        }
      );
    }

    this.infoTimeOut = setTimeout(() => {
      if (!backendAvailable) {
        subscription.unsubscribe()
        this.showMessage("error");
        this.stopLoadingBar();
      }
    }, 120000);
  }

=========================================================================

Ans:

This is the most close solution to what I want:

 checkBackend() {
    console.log('Waiting for backend...');
    
    let infoObservable = this.infoService.getInfo().pipe(
      retryWhen(errors =>
        errors.pipe(
          delay(10000),
          tap(errorStatus => {
            //stop timeout if error
            this.stopInfoTimeOut();
            //parse the error, depending on the return from the http.get
            if (!errorStatus.includes('504')) {
              throw errorStatus;
            }
            //run timeout when trying a new request
            this.runInfoTimeout();
          })
        )
      ))
      
    this.infoSubscription= infoObservable.subscribe({
      next: val => {
        if (val) {
          console.log('Backend available');
          this.stopInfoTimeOut();
        }
      },
      error: val => {
        console.log(val);
        this.stopInfoTimeOut();
        this.showMessage("Backend not available, try later");
      }, 
      complete: () => {}
    })


No comments:

Post a Comment

How to register multiple implementations of the same interface in Asp.Net Core?

 Problem: I have services that are derived from the same interface. public interface IService { } public class ServiceA : IService { ...