Angular interceptors with async/await
I like working with promises
, and interceptors (and Angular) usually use observables
. Async/await also makes promises so much easier to read and maintain, so that’s why I prefer working with it. It’s, however, a bit complicated to set up and work with, this is one way you can accomplish it.
Scroll to the bottom for a TL;DR.
Full example
Like most other Angular function, we will use an RxJS
operator called from, which turns a promise
into an observable
.
Let’s say this is our base interceptor.
import { HttpInterceptor } from "@angular/common/http";
import { Injectable } from "@angular/core";
@Injectable()
export class ExampleInterceptor implements HttpInterceptor {
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
// ...
}
}
In this example, we will try to catch a 401 error, and handle that asynchronously with async/await. For this, we will also use the catchError operator from RxJS
.
return next.handle(request).pipe(
catchError((error) => {
if (error instanceof HttpErrorResponse && error.status === 401) {
// ...
}
})
);
The most important logic, the one which lets us use promises. We need to create a new asynchronous method and call it with the from
operator.
from(this.handle401Error(request, next));
The function might look something like this.
private async handle401Error(request: HttpRequest<any>, next: HttpHandler) {
const newRequest = await this.someService.asyncChange(request);
return next.handle(newRequest).toPromise();
}
We need to use the toPromise()
function to turn it into a promise
, which the from
operator will turn back to an observable
.
This is the final code.
import { HttpInterceptor} from '@angular/common/http';
import { Injectable } from '@angular/core';
@Injectable()
export class ExampleInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
from(this.handle401Error(request, next));
}
}))
}
private async handle401Error(request: HttpRequest<any>, next: HttpHandler) {
const newRequest = await await this.someService.asyncChange(request);
return next.handle(newRequest).toPromise();
}
}
TL;DR
The code above might look a bit cluttered. The most important parts are these two:
if (error instanceof HttpErrorResponse && error.status === 401) {
from(this.handle401Error(request, next));
}
private async handle401Error(request: HttpRequest<any>, next: HttpHandler) {
const newRequest = await await this.someService.asyncChange(request);
return next.handle(newRequest).toPromise();
}