Error Handling in Observables - Angular
Last Updated :
17 Apr, 2024
In Angular applications, we often work with asynchronous data streams, which are represented by Observables. While Observables provide a powerful way to handle asynchronous operations, it's important to handle errors that may occur during the subscription to prevent your application from crashing.
Error handling in Observables is a crucial aspect of building robust and reliable Angular applications. When an error occurs, the Observable will terminate, and any subsequent emissions will be ignored. If the error is not handled properly, it can lead to unexpected behavior or even application crashes.
Approach for handling errors in Observables
Angular provides several ways to handle errors in Observables. Here are the main approaches:
1. catch Operator
The catch operator is used to handle errors in Observables. When an error occurs, the catch operator is responsible for catching and handling that error. It takes an error handler function as an argument, which allows you to handle the error or return a new Observable.
Syntax:
import { catchError } from 'rxjs/operators';
observable.pipe(
catchError((error) => {
// Handle the error
return fallbackValue; // or throwError('Custom error message')
})
);
2. throwError and catchError
The throwError utility function is used to create an Observable that emits a specified error. It's often used in combination with the catchError operator, which allows you to handle the error and optionally return a new Observable or a default value.
Syntax:
import { throwError } from 'rxjs';
throwError('Custom error message');
3. retry Operator
The retry operator is used to retry an Observable a specified number of times in case of an error. It takes a count argument, which determines the number of times the Observable should be retried before propagating the error.
Syntax:
import { retry } from 'rxjs/operators';
observable.pipe(
retry(3) // Retry the observable up to 3 times
);
4. retryWhen Operator
The retryWhen operator is similar to the retry operator, but it provides more flexibility and control over the retry logic. It takes a function that receives an Observable of error notifications and returns an Observable that signals when to retry.
Syntax:
import { retryWhen, delay, take } from 'rxjs/operators';
observable.pipe(
retryWhen(errors => errors.pipe(
delay(1000), // Delay retry attempts by 1 second
take(3) // Retry the observable up to 3 times
))
);
5. finalize Operator
The finalize operator is used to execute some cleanup logic when the Observable completes, regardless of whether it completed successfully or with an error.
Syntax:
import { finalize } from 'rxjs/operators';
observable.pipe(
finalize(() => {
// Perform cleanup actions
})
);
Example:
To better understand these approaches, let's create an Angular application and implement each one individually.
Step 1: Create a new Angular application using the Angular CLI:
ng new error-handling-demo
Step 2: Navigate to the project directory
cd error-handling-demo
Step 3: Create a service
ng generate service data
Folder Structure:
Project structure
Code Example:
HTML
<!-- app.component.html -->
<h1>Error Handling in Observables</h1>
<button (click)="useCatchOperator()">Use catch Operator</button>
<button (click)="useThrowErrorAndCatchError()">Use throwError and catchError</button>
<button (click)="useRetryOperator()">Use retry Operator</button>
<button (click)="useRetryWhenOperator()">Use retryWhen Operator</button>
<button (click)="useFinalizeOperator()">Use finalize Operator</button>
JavaScript
//data.service.ts
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
constructor() { }
getData(): Observable<string> {
return throwError('Simulated error occurred');
}
}
JavaScript
//app.component.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { DataService } from './data.service';
import { catchError, delay, finalize, retry, retryWhen, tap, throwError } from 'rxjs';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
constructor(private dataService: DataService) { }
useCatchOperator() {
this.dataService.getData()
.pipe(
catchError(error => {
console.error('Error caught:', error);
return throwError('Error handled using catch operator');
})
)
.subscribe(
data => console.log(data),
error => console.error('Error:', error)
);
}
useThrowErrorAndCatchError() {
this.dataService.getData()
.pipe(
catchError(error => {
console.error('Error caught:', error);
return throwError('Error handled using catchError');
})
)
.subscribe(
data => console.log(data),
error => console.error('Error:', error)
);
}
useRetryOperator() {
this.dataService.getData()
.pipe(
retry(3)
)
.subscribe(
data => console.log(data),
error => console.error('Error:', error)
);
}
useRetryWhenOperator() {
this.dataService.getData()
.pipe(
retryWhen(errors => errors.pipe(
tap(error => console.error('Retrying after error:', error)),
delay(2000)
))
)
.subscribe(
data => console.log(data),
error => console.error('Error:', error)
);
}
useFinalizeOperator() {
this.dataService.getData()
.pipe(
finalize(() => console.log('Finalize executed'))
)
.subscribe(
data => console.log(data),
error => console.error('Error:', error)
);
}
}
To start the application run the following command.
ng serve
Output

Make sure to import the required RxJS operators in the component file for each approach you want to implement.
By running the application (ng serve --open) and clicking the respective buttons, you can see the different error handling approaches in action and observe the console output.
Similar Reads
Error Handling in RxJava While developing an Android App we come across a lot of errors. Even a single line of code can cause an error which can ruin the whole project. There are many different types of Errors and each needs a different way of handling them but in this article, we are specifically going to focus on Error ha
7 min read
Angular 7 | Observables Observables provide support for data sharing between publishers and subscribers in an angular application. It is referred to as a better technique for event handling, asynchronous programming, and handling multiple values as compared to techniques like promises.A special feature of Observables is th
7 min read
Binding Syntax In Angular In Angular, binding syntax lets you determine the channel of data transmission between the component class and the template. Among various types of bindings supported by Angular are interpolation, property binding, event binding, and two-way-data-binding. Therefore, it is important to understand var
3 min read
How to Subscribe to an Observable in Angular? In Angular, managing data streams effectively is important, especially when dealing with asynchronous operations. Observables, a core part of the RxJS library used in Angular, are powerful tools for handling these data streams. In this article, we will explore how to subscribe to Observables in Angu
4 min read
AngularJS $exceptionHandler Service In AngularJS, a service is a function or object that is available for dependency injection (DI) in an AngularJS app. Services are typically used to encapsulate and reuse business logic and other app functionality that is not directly related to the presentation of data in the app. The $exceptionHand
4 min read