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