How to retry an HTTP request in Angular (with plenty of code examples)
Tags: angular
Published: 2020-12-07 15:32:19

## How do you gracefully deal with a failed HTTP request?
#### Here's the few lines of Angular code you can use to manage HTTP failures.

Some Angular apps can be as clumsy as a soccer-playing elephant. When they fail they fall HARD.

![](https://danielk.tech/user/pages/01.home/angular-retry-an-http-request/elephant%20retry.gif)

And others are as nimble as a head-bonking rock star. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0y4mv1o6qcgnigvx30fb.gif)

Interested in knowing how you can make your Angular web app more nimble and tough by gracefully handing HTTP failures? Read on.

## It starts with an [HTTP interceptor](https://angular.io/guide/http#intercepting-requests-and-responses)

Open a terminal in your Angular project and whip it up with the [Angular CLI](https://cli.angular.io/) like so.

```bash
ng generate interceptor monitor
```

And then we'll import it into our module file by adding it to the `providers` array.

```typescript
providers: [
    { 
      provide: HTTP_INTERCEPTORS, 
      useClass: MonitorInterceptor, 
      multi: true
    }
]
```

## Wield the interceptor to retry failed requests

Next we'll open the new `monitor.interceptor.ts` file. It should look something like this.

```typescript
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class MonitorInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request);
  }
}
```

As you probably already know this interceptor can be used to modify any incoming or outgoing HTTP requests.

How do we get the benefits of an Angular interceptor? The answer is simple.

To add the retry capability we'll use the [retry](https://rxjs.dev/api/operators/retry) function that triggers a retry when the Observable fails.

Here's how you do it buster.

```typescript
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { retry } from 'rxjs/operators';

export const retryCount = 3;

@Injectable()
export class MonitorInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(
      retry(retryCount)
    )
  }
}
```

Now if any HTTP request fails it will retry that request another 3 times. 

## How do you retry on certain response status codes?

```typescript
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { concatMap, delay, retryWhen } from 'rxjs/operators';

export const retryCount = 3;
export const retryWaitMilliSeconds = 1000;

@Injectable()
export class MonitorInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(
      retryWhen(error => 
        error.pipe(
          concatMap((error, count) => {
            if (count <= retryCount && error.status == 503) {
              return of(error);
            }
            return throwError(error);
          }),
          delay(retryWaitMilliSeconds)
        )
      )
    )
  }
}
```

## How do you resend request after a reauthentication proceedure like a token refresh?

How do a handle a scenario when the server responds with a `401`? And you need to do some sort of login or token refresh?

Here's the code.

```typescript
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';

export const retryCount = 3;

@Injectable()
export class MonitorInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(catchError(error => {
        if (error.status === 401) {
          return this.reAuthenticate().pipe(
            switchMap(() => next.handle(request))
          )
        }
        return throwError(error);
      })
    )
  }

  reAuthenticate(): Observable<any> {
    // Do your auth call here
  }
}
```

You can find a more elaborate example [here](https://stackoverflow.com/questions/45202208/angular-4-interceptor-retry-requests-after-token-refresh).

## Conclusion

In this guide we've looked at different ways to gracefully handle a failed HTTP request.

Failing gracefully might seem like a small detail that's not worth batting an eye-lid at but when done properly your users will be appreciative.

Questions or comments? Please don't hesitate to poke me.

![](https://danielk.tech/user/pages/01.home/angular-retry-an-http-request/signature.png)