javascript / expert
Snippet
Recoverable Error Boundaries with RxJS catchError Chains
Demonstrates a layered error-recovery strategy for an Angular service: bounded retries for transient network issues, a timeout guard against hanging requests, and a custom error class that distinguishes recoverable server failures (silently substituted with defaults) from unrecoverable ones (rethrown for the caller to handle). This avoids the common anti-pattern of either swallowing every error or crashing the component on any failure.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { Injectable } from '@angular/core';import { HttpClient, HttpErrorResponse } from '@angular/common/http';import { Observable, throwError, of } from 'rxjs';import { catchError, retry, timeout } from 'rxjs/operators';class RecoverableApiError extends Error {constructor(message: string, public readonly statusCode: number, public readonly fallbackUsed: boolean) {super(message);this.name = 'RecoverableApiError';}}@Injectable({ providedIn: 'root' })export class ResilientConfigService {constructor(private http: HttpClient) {}loadConfig(): Observable<Record<string, unknown>> {return this.http.get<Record<string, unknown>>('/api/config').pipe(timeout(3000),retry({ count: 2, delay: 500 }),catchError((err: HttpErrorResponse) => {if (err.status >= 500) {console.error(new RecoverableApiError('Server unavailable, using defaults', err.status, true));return of({ theme: 'default', locale: 'en' });}return throwError(() => new RecoverableApiError('Config fetch failed', err.status, false));}),);}}
angular
Breakdown
1
class RecoverableApiError extends Error
A custom error subclass carrying structured metadata (statusCode, fallbackUsed) so downstream handlers can branch on error semantics rather than parsing message strings.
2
retry({ count: 2, delay: 500 })
Limits retries to two attempts with a fixed delay, preventing an unbounded retry storm against a struggling backend.
3
return of({ theme: 'default', locale: 'en' });
Silently degrades to safe defaults for 5xx errors instead of failing the whole app shell.