We have a case where we use observable to populate the UI from the external data asynchronously. Angular uses same thing for this task. Let’s see how we can use the observables and use them in an Angular application.
What are Observables?
Observables are lazy collections of multiple values or we can say, data over a period. Observables open the continuous channel of communication where multiple values are emitted over time. This allows us to determine the pattern of the data.
In a real-world example, we can say Internet service offered by the mobile is observable. It is available only to the people who have subscribed to it. We continuously receive this service from the service provider only until this service is ON and subscribed.
Creating the basic observable
Let’s create the basic observable first and let’s see what they offer us. The code snippet for the same can be like below.
- import { Component, OnInit } from '@angular/core';
- import {Observable} from 'rxjs/Observable'
- @Component({
- selector: 'app-observable-demo',
- templateUrl: './observable-demo.component.html',
- styleUrls: ['./observable-demo.component.css']
- })
- export class ObservableDemoComponent implements OnInit
- {
- private data: Observable<string>;
- private fruits: Array<string> = [];
- private anyErrors: boolean;
- private finished: boolean;
-
- processed=false;
-
- constructor() { }
- ngOnInit(){
- }
-
- Start(){
- this.data = new Observable
- (
- observer =>
- {
- setTimeout(() =>
- {
- observer.next('Apple');
- }, 1000);
-
- setTimeout(() =>
- {
- observer.next('mango');
- }, 2000);
- setTimeout(() =>
- {
- observer.next('Orannge');
- }, 3000);
- setTimeout(() =>
- {
- observer.complete();
- }, 4000);
-
- }
- );
- let subscription = this.data. subscribe(
- fruit => this.fruits.push(fruit),
- error => this.anyErrors = false,
- () => this.finished = true
- );
- this.processed=true; }}
Let’s see the code description step by step,
- Import the observable from rxjs/Observable and include in the component
- next is to create the observable object which in our example we are creating the observable object which will be of string
- Next thing is to subscribe the Observable in the application which will allow us to listen to the data that is coming along with it
- While subscription we used three callbacks first which already accepts the data emitted by
The second observable is the Error call back, and the third one is the successful callback which will be called when the whole data has been received.
To invoke this observable, we need to do some changes at the template that we are doing. The code snippet for the template can be like this,
- <p style="padding-left:300px;font-weight:bold;font-size: 50px">Observable Basics</p>
- <hr/>
- <b>Observable Data </b>
- <div style="border: 3px;padding-left:150px;text-align: " *ngFor="let f of fruits"> {{ f | uppercase }}</div>
- <hr>
- <div *ngIf='anyErrors' style="border: 3px;padding-left:0px" >
- <b>Error Status :</b>
- {{anyErrors==true? 'error occured ' : 'It All Good'}}
- <hr>
- </div>
- <div style="border: 3px;padding-left:0px"> <b> completion status : </b> {{ finished==true ? 'Observer completed ': '' }}</div>
- <hr>
- <button style="margin-top: 2rem;" (click)="start()">Start Emitting</button>
The above code displays the fruit names that we are emitting in the application output.
So, when we see the output, we will see the above output.
The next thing we want to see is how we can handle the error in observers.
Error Handling in Observables
There might be a case where an error is generated when we are using the observables. If some unexpected occurs in between, we can use the observable error function in our subscription to check what went wrong.
Let’s check the component code for the same.
- import { Component, OnInit } from '@angular/core';
- import {Observable} from 'rxjs/Observable'
- @Component({
- selector: 'app-observable-demo',
- templateUrl: './observable-demo.component.html',
- styleUrls: ['./observable-demo.component.css']
- })
- export class ObservableDemoComponent implements OnInit {
- private data: Observable<string>;
- private fruits: Array<string> = [];
- private anyErrors: boolean;
- private finished: boolean;
-
- processed=false;
-
- constructor() { }
- ngOnInit(){
- }
-
- start(){
- this.data = new Observable
- (
- observer =>
- {
- setTimeout(() =>
- {
- observer.next('Apple');
- }, 1000);
-
- setTimeout(() =>
- {
- observer.next('mango');
- }, 2000);
- setTimeout(() =>
- {
- observer.next('Orannge');
- }, 3000);
- setTimeout(() =>
- {
- observer.error(new Error('error occured'));
- }, 4000);
- setTimeout(() =>
- {
- observer.complete();
- }, 5000); });
- let subscription = this.data.
- subscribe(
- fruit => this.fruits.push(fruit),
- error => this.anyErrors = true,
- () => this.finished = true
- );
- this.processed=true; }}
We can see the output here like below.
Thing to consider in this case is that we cannot see the completion status shown when the Emit event is done
This is because the complete event won’t be fired if it is added after the error in the coding so we should always have some function which will stop all the running component in the application.
Using observables for the Form Events
Let’s see how we use the observables in the angular forms
Component that we will be using will be like below,
- import { Component, OnInit } from '@angular/core';
- import {Observable} from 'rxjs/Observable'
- import {FormControl, FormGroup, FormBuilder} from '@angular/forms';
- import 'rxjs/add/operator/map';
-
- @Component({
- selector: 'app-observable-demo',
- templateUrl: './observable-demo.component.html',
- styleUrls: ['./observable-demo.component.css']
- })
- export class ObservableDemoComponent implements OnInit {
- private data: Observable<string>;
- private fruits: Array<string> = [];
- private anyErrors: boolean;
- private finished: boolean;
- mathform: FormGroup;
- inputnumber :FormControl
- squaredata:number;
- processed=false;
-
- constructor(private fb: FormBuilder) {
-
- this.inputnumber=new FormControl();
-
- this.mathform = fb.group({
- inputnumber:this.inputnumber
- })
- this.inputnumber.valueChanges.map(n=>n*n)
- .subscribe(power=>this.squaredata=power);
- };
Here we have used the Reactive form. In this whenever we use the reactive forms every field is considered as observable we can subscribe to that field and listen to any changes made to that input value
In the above snippet, we have created the form by using the formcontrol and added to the formgroup. This control has the property valuechanges which always returns the observable. Now, whenever I type the number in the field, I get the square of that number.
Template code can be like below for the above change.
- <form [formGroup]="mathform">
- <input formControlName="inputnumber">
- </form>
- <hr>
- <div>
- Square of the number is :: <b>{{squaredata}}</b>
- </div>
The output for the same can be like below.
Unsubscribing from the Observable
There are chances that we need to unsubscribe from the observable and do some cleanup like resource release. Unsubscribe() will unhook the members listening to the Observable stream. Also, there is a way to provide the custom call back method OnUnsubscribe() which will be called to manually clean up the things after the subscription has been ended.
Do we need to call unsubscribe every time we call the observables? The answer is no, observables have a built-in ability to dispose of all the resources whenever the Complete or the error method gets called in the application.
Hot and Cold Observables
Generally, there are two types of the observables; the first one is Cold observable and the other one is Hot observable
What are cold observables?
Cold observables are the ones which are explicitly invoked by the producer in our first example where we used the set timeout method we were manually creating and subscribing the observable inside the start functions -- this is cold observable.
What are hot observables?
In contrast to the cold observable we have hot observables, which we do while getting the power of the number which is invoked as soon as the value change occurs, it will start subscribing the stream before waiting for the producer to send the signal to subscribe.
So, this was all about the observables. In the next article, we will see how we can use the observable with the HttpClient for calling the HTTP method and how we can transform the result and get the error.
Source code for the same can be found on this Link
References
- https://hackernoon.com/understanding-creating-and-subscribing-to-observables-in-angular-426dbf0b04a3
- https://rangle.io/