Issue
I have an Angular HttpInterceptor
to catch errors and display appropriate, yet generic, error messages depending on the status code.
I have a specific case where I actually expect and error message (the UI tries to release a lock on a resource that has just been deleted, so I get 404).
In that case I want to handle the error directly where I make the API call, and skip the interceptor.
I tried this:
releaseReviewerLock(itemType: EquipmentItemType, itemId: EquipmentItem["id"]): Observable<void> {
return this.http
.post<void>(`${this.configUrl}/${itemType.toLowerCase()}/${itemId}/release-reviewer-lock/`, {})
.pipe(
catchError(e => {
if (e.status === HttpStatusCode.NotFound) {
// We can ignore the 404 because the item has just been deleted, so there's nothing to release.
return EMPTY;
}
})
);
}
But not only is my intercepto called anyway, the catchError
block above is not executed at all (breakpoint didn't stop).
Can I achieve what I want without modifying the interceptor and keeping a resemblance of single-responsibility?
Thanks!
Solution
We can pass some metadata context to HttpClient
and then retrieve it inside the HttpInterceptor
.
Of course, it implies to add some logic inside HttpInterceptor
, but thanks to metadata context, this code could be more versatile, and stay simple.
For example:
In api.service.ts
:
this.httpClient
.get('http://...', {
context: new HttpContext().set(IGNORED_STATUSES, [404]),
})
.pipe(
catchError((e) => {
console.log('Error catched locally', e);
return of(EMPTY);
})
)
.subscribe();
In error.interceptor.ts
:
export const IGNORED_STATUSES = new HttpContextToken<number[]>(() => []);
export class CustomHttpInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const ignoredStatuses = req.context.get(IGNORED_STATUSES);
return next.handle(req).pipe(
catchError((e: HttpErrorResponse) => {
// if ignored statuses are set
// and returned status matched
if (ignoredStatuses?.includes(e.status)) {
// rethrow error to be catched locally
return throwError(() => e);
}
// process error...
console.log('error interceptor !!', e);
return of();
})
);
}
}
Answered By - Thierry Falvo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.