In order to guarantee a seamless user experience and facilitate debugging, Angular error management entails recording and controlling errors. Angular comes with a number of built-in tools and methods for methodically managing faults.


1. Managing Errors in HTTP

The HttpClient and the catchError operator from RxJS can be used to manage errors in HTTP requests.

For instance
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { catchError, throwError } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class DataService {
  private apiUrl = 'https://api.example.com/data';

  constructor(private http: HttpClient) {}

  getData() {
    return this.http.get(this.apiUrl).pipe(
      catchError(this.handleError)
    );
  }

  private handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      // Client-side error
      console.error('Client-side error:', error.error.message);
    } else {
      // Server-side error
      console.error(`Server-side error: ${error.status} - ${error.message}`);
    }
    return throwError(() => new Error('Something went wrong; please try again later.'));
  }
}


catchError: Intercepts errors and allows custom handling.
throwError: Re-throws the error after handling it for further processing.

2. Global Error Handling
Angular provides a way to handle application-wide errors using the ErrorHandler service.

Custom Global Error Handler.
Create a custom error handler.
import { ErrorHandler, Injectable, NgZone } from '@angular/core';

  @Injectable()
  export class GlobalErrorHandler implements ErrorHandler {
    constructor(private ngZone: NgZone) {}

    handleError(error: any): void {
      // Log the error to the console or a logging service
      console.error('Global Error:', error);

      // Notify the user (e.g., using a toast or modal)
      this.ngZone.run(() => {
        alert('An unexpected error occurred.');
      });
    }
  }
   

Register the error handler in AppModule.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { GlobalErrorHandler } from './global-error-handler';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [{ provide: ErrorHandler, useClass: GlobalErrorHandler }],
  bootstrap: [AppComponent]
})
export class AppModule {}

The service will be used throughout the entire application to catch logs.

3. Error Interceptors
Use an HTTP interceptor to handle errors globally for all HTTP requests.

Example

Create an HTTP interceptor.
  import { Injectable } from '@angular/core';
  import { HttpInterceptor, HttpRequest, HttpHandler, HttpErrorResponse } from '@angular/common/http';
  import { catchError, throwError } from 'rxjs';

  @Injectable()
  export class ErrorInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler) {
      return next.handle(req).pipe(
        catchError((error: HttpErrorResponse) => {
          // Handle different error types
          if (error.status === 404) {
            console.error('Not Found:', error.message);
          } else if (error.status === 500) {
            console.error('Server Error:', error.message);
          }

          // Optionally, rethrow the error
          return throwError(() => new Error('An error occurred. Please try again later.'));
        })
      );
    }
  }
   

Register the interceptor in AppModule.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AppComponent } from './app.component';
import { ErrorInterceptor } from './error-interceptor';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: ErrorInterceptor,
      multi: true
    }
  ],
  bootstrap: [
    AppComponent
  ]
})
export class AppModule {}

4. Using Angular Guards for Route Error Handling
Angular guards can protect routes and handle access-related errors.
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(): boolean {
    const isAuthenticated = false; // Replace with actual authentication logic
    if (!isAuthenticated) {
      alert('You are not authorized to access this page.');
      this.router.navigate(['/login']);
      return false;
    }
    return true;
  }
}


5. Error Display in the UI
Display user-friendly error messages in the UI using Angular components.

Example
Create an error message component.
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-error-message',
  template: `
    <div *ngIf="errorMessage" class="error">
      {{ errorMessage }}
    </div>
  `,
  styles: [
    `
      .error {
        color: red;
      }
    `,
  ],
})
export class ErrorMessageComponent {
  @Input() errorMessage: string | null = null;
}



Use the component.
<app-error-message [errorMessage]="error"></app-error-message>

6. RxJS Error Handling Strategies
    Retry Failed Requests.
    import { retry } from 'rxjs';

    this.http.get(this.apiUrl).pipe(
      retry(3), // Retry up to 3 times
      catchError(this.handleError)
    );

Fallback Data.
this.http.get(this.apiUrl).pipe(
  catchError(() => of([])) // Return fallback data on error
);


7. Logging Errors
Use external services like Sentry, LogRocket, or custom logging services to log errors.

Example
@Injectable({
  providedIn: 'root'
})
export class LoggingService {
  logError(message: string, stack: string) {
    // Send error logs to an external server
    console.log('Logging error:', message);
  }
}