Overview
Angular leverages a powerful tool called “Observables” to handle a wide range of asynchronous tasks, such as handling HTTP requests, user interactions, and real-time data updates. This article will provide a thorough explanation of Observables in Angular, including their concepts, use cases, and how to work with them effectively.
What is an Observable?
An Observable is a core part of the Reactive Extensions for JavaScript (RxJS) library, and Angular makes extensive use of RxJS observables. At its core, and Observable is a data stream that emits value over time. These values can represent a single value, multiple values, or even an infinite sequence of values. Observables enable you to work with asynchronous data in a more declarative and composable manner.
An Observable is a wrapper around asynchronous data. We use an observable to handle asynchronous data.
or we can say that, an observable is a function that converts the ordinary data stream into an observable one. You can think of Observable as a wrapper around the ordinary data stream.
What is synchronous programming?
As we already know that JavaScript is a single-threaded programming language. It means in the code is executed line by line one after other in order in which they are defined. So once the execution of one line is completed only then next line of code is executed.
So if a task takes a long time in execution, then next line of code will have to wait for its execution. It will be executed only after the previous code execution is completed.
For example, we are making an HTTP request to the server to get some data, now data will come as a response from the server. This HTTP request response cycle, it might take some time to complete. So if we are making an HTTP request using synchronous code then the next line of code after HTTP request will be executed only after we received the response from the server. So we can say that synchronous code is blocking in nature. This is where asynchronous programming comes into the picture.
What is asynchronous programming?
Asynchronous code does not execute in single-threaded. It gets executed in the background.
- Asynchronous code is non blocking in nature.
When we make HTTP request asynchronously it will run in the background and the next code after the request will be executed immediately in the main thread and in this way HTTP request will not block the execution of next line of code. So using asynchronous programming we can perform time consuming requests without blocking the main thread. Now asynchronous request return some data after some time, so we need to wait for that data and once the data is available we can utilize it in our code. To handle that asynchronous data we use either a promise or an observable.
What is Data Streaming?
Instead of sending data all at once in a big chunk, data streaming sends data to the client in small chunks.
Promise Vs Observable
A promise promises a data over a period of time, that data which promises it can be actual data or it can also be an error. Let us say we made an HTTP request to server, a promise will return us response data if everything is okay or it will return us an error object if something went wrong. If there is some network issue then promise will return an error object But if there is no error we received the response data successfully.
- A promise cannot handle stream of asynchronous data. It always returns a single value. On the other hand, we can use observables to handle stream of asynchronous data. It can return multiple values.
- A promise will certainly return a data even if no code is using that data. Whereas an observables will return a data only if someone is going to use that data.
- A promise is native to JavaScript program. Whereas observable is not native to JavaScript and it is provided by “RxJS” library.
Observable Pattern
The Observable pattern, also known as the Observer pattern, is a behavioral design pattern where an object (the subject) maintains a list of dependents (observers) that need to be notified of any changes in its state. When the state of the subject changes, it notifies all its observers, allowing them to react accordingly.
In the context of programming, the Observable pattern is widely used to implement reactive programming, event handling, and asynchronous data streams.
- Observable (Subject): (Event Emitter)
- The subject is the source of values or events that observers can subscribe to.
- It represents a data stream that can emit multiple values over time.
- Observables can be created from various sources such as DOM events, HTTP responses, timers, or custom data streams.
- Observer (Subscriber): (Event Listener)
- Observers are objects that subscribe to the observable to receive notifications of value changes or events.
- They define methods (next, error, complete) to handle emitted values, errors, and completion notifications from the observable.
- Subscription:
- A subscription represents the connection between an observable and an observer.
- It allows observers to unsubscribe from the observable to stop receiving notifications when they are no longer interested.
- Operators:
- Operators are functions that enable powerful transformation, combination, and filtering of observables.
- They allow you to modify, filter, or transform data streams using a variety of functional programming techniques.
Key Concepts of Observables
To understand Observables better, let's explore some key concepts:
- Observable Stream: An Observable is a source of data that can emit values over time. It can emit any type of data, such as number, strings, objects, or custom data structures.
- Observer: An Observer subscribes to an Observable and listens for the emitted values. It defines how to react when data is emitted, specifying what to do on successful emissions or in the case of errors or completion.
- Subscription: When an Observer subscibes to an Observable, it created a Subscription. This subscription represents the connection between the Observer and the Observable. Subscriptions can be used to unsubscribe from the Observable when it is no longer needed, preventing memory leaks.
- Operators: Observables can be transformed and modified using operators. Operators are functions that can be chained together to manipulate, filter, transform, or combine the data emitted by an Observable.
Working with Observables in Angular
Here's a step-by-step guide on how to work with Observables in Angular:
1. Import RxJS Library
First, make sure you have the RxJS library installed and import in into your Angular component or service.
import { Observable } from 'rxjs';
2. Create an Observable
You can create an Observable from various sources, such as custom data or events. For example:
const customObservable = new Observable((observer) => {
// emit values
observer.next('Hello');
observer.next('World');
observer.complete();
});
3. Subscribe to an Observable
To listen to the emitted values, you need to subscribe to the Observable:
// Subscribe to the observable
customObservable.subscribe(
(data) => console.log(data), // Handle emitted data
(error) => console.error(error), // Handle errors
() => console.log('Observable completed') // Handle completion
);
Since we subscribe to that observable, any event that observable will emit, this code will be notified.
4. Use Operators
You can use RxJS operators to transform or filter the emitted data:
import { map, filter } from 'rxjs/operators';
customObservable
.pipe(
map((data) => data.toUpperCase()),
filter((data) => data.startsWith('H'))
)
.subscribe((data) => console.log(data));
5. Unsubscribe
It's essential to unsubscribe from Observables to prevent memory leaks. You can store the subscription in a variable and unsubscribe when it's no longer needed.
const subscription = customObservable.subscribe((data) => console.log(data));
subscription.unsubscribe();
Simple Observable Example
Step 1
Import observable from rxjs in your component in angular.
import { Observable } from 'rxjs';
Step 2
Create a simple observable that will emit 1 to 5 as data stream.
myObservable = new Observable((observer) =>{
console.log('Observable Starts')
observer.next("1")
observer.next("2")
observer.next("3")
observer.next("4")
observer.next("5")
});
Step 3
Subscribe observable to get the emit value in the ngOnInit hook method.
ngOnInit(){
this.myObservable.subscribe((val)=>{
console.log(val);
});
}
Output:
Now lets do modification and emit the data at the interval of 1 sec.
myObservable = new Observable((observer) =>{
console.log('Observable Starts')
setTimeout(()=>{observer.next("1")},1000)
setTimeout(()=>{observer.next("2")},2000)
setTimeout(()=>{observer.next("3")},3000)
setTimeout(()=>{observer.next("4")},4000)
setTimeout(()=>{observer.next("5")},5000)
});