The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of state changes. This pattern is similar (but not identical) to the publish/subscribe design pattern.
Angular Observables support passing the messages between publishers(Creator of Observables) and subscribers(Users of Observables) in your application. Observables are declarative; you define the function for publishing values, but it is not executed until the consumer subscribes.
Depending on the context, the observable can deliver multiple values, like literals, messages, or events. For example, as a publisher, you can create an Observable instance that defines a subscriber function. This function is executed when the consumer calls the subscribe() method.
Define Angular Observers
The handler for receiving the observable notifications implements the Observer interface. It is an object that defines the callback methods to handle the three types of notifications that an observable can send. These are the following.
- next: Required. The handler for each delivered value is called zero or more times after execution starts.
- error: Optional. The handler for error notification. The error halts the execution of the observable instance.
- complete: Optional. The handler for an execution-complete notification. The delayed values can continue to be delivered to the next handler after execution.
Subscribing Angular Observables
An important note is that the Observables instance only publishes the values when someone subscribes. You can subscribe to the observables by calling the subscribe() method of the instance and passing an observer object to receive the notifications.
myObservable.subscribe( x => console.log('Observer got a next value: ' + x), err => console.error('Observer got an error: ' + err), () => console.log('Observer got a complete notification') );
Creating Angular Observables
Use the Observables constructor to create an observable stream of any type.
const obs = new Observable();
Here is a step-by-step guide to implement Observables in Angular.
Step 1: Create an Angular Project
Type the following command to create an Angular project using Angular CLI.
ng new observe
Install the Bootstrap CSS Framework.
npm install bootstrap --save
Step 2: Create a service and model files
Create an Angular service.
ng g s student --spec=false
It will create a student.service.ts file inside the src >> app folder.
We have created a service because we will use the service to handle the data that needs to be displayed on the front end.
Create a new file inside a src >> app directory called student.model.ts and add the following code.
// student.model.ts export class Student { id: Number; name: String; EnrollmentNumber: Number; College: String; University: String; }
That means we have defined the Student type in our application: the id, name, enrollment number, college, and university properties.
We need to add the demo data inside the student.service.ts file. The data is the type of Student model that we have defined above.
// student.service.ts import { Injectable } from '@angular/core'; import { Student } from './student.model'; @Injectable({ providedIn: 'root' }) export class StudentService { students: Student[] = [{ id: 1, name: 'Krunal', enrollmentnumber: 110470116021, college: 'VVP Engineering College', university: 'GTU' }, { id: 2, name: 'Rushabh', enrollmentnumber: 110470116023, college: 'VVP Engineering College', university: 'GTU' }, { id: 3, name: 'Ankit', enrollmentnumber: 110470116022, college: 'VVP Engineering College', university: 'GTU' }]; constructor() { } }
Step 3: Create an Observable
Add the following code inside the student.service.ts. Put the getStudents() function inside the class after the constructor.
// student.service.ts import { Observable } from 'rxjs'; public getStudents(): any { const studentsObservable = new Observable(observer => { setTimeout(() => { observer.next(this.students); }, 1000); }); return studentsObservable; }
Step 4: Define the Subscriber
Write the following code inside the app.component.ts file.
// app.component.ts import { Component, OnInit } from '@angular/core'; import { Student } from './student.model'; import { StudentService } from './student.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { students: Student[] = []; constructor(private studentservice: StudentService) {} ngOnInit() { const studentsObservable = this.studentservice.getStudents(); studentsObservable.subscribe((studentsData: Student[]) => { this.students = studentsData; }); } }
We have subscribed to the observable and gotten the student’s data here.
The final step is to display the data.
Step 5: Display the data
Add the following code inside the app.component.html file.
<!-- app.component.html> <div class="container"> <div class="row" style="margin-top: 30px"> <div class="col-md-3 col-xs-6" *ngFor="let student of students"> <div class="card"> <div class="card-body"> <h5 class="card-title">{{ student.name }}</h5> <h6 class="card-subtitle">{{ student.enrollmentnumber }}</h6> <p class="card-text">{{ student.college }}</p> <p class="card-text">{{ student.university }}</p> <a class="btn btn-primary" href="#" >Go somewhere</a> </div> </div> </div> </div> </div>
Save the file and start the angular development server.
ng serve
Go to http://localhost:4200 and see the result after 1 second.
So, we have successfully got the data using Observables.
Simple Code of Observables
import { Observable } from "rxjs/Observable" // create observable const simpleObservable = new Observable((observer) => { // observable execution observer.next("hello") observer.complete() }) // subscribe to the observable simpleObservable.subscribe() // dispose the observable simpleObservable.unsubscribe()
Error handling
The Observables produce values asynchronously, so the try/catch block will not effectively work here to catch the errors. So, In the sense of Observables, you can handle the errors by specifying an error callback on the observer.
Producing an error also causes the observable to clean up subscriptions and stop producing values. An observable can either produce the values (calling the next callback) or it can complete, calling either the complete or error callback.
myObservable.subscribe({ next(num) { console.log('Next num: ' + num)}, error(err) { console.log('Received an errror: ' + err)} });
Disposing of observables
When you subscribe to the Observable, you get back the subscription, representing an ongoing execution. Just call unsubscribe() to cancel the execution. So you are free to that Observable.
You can find more about Angular Observables here.
Krunal Lathiya is a seasoned Computer Science expert with over eight years in the tech industry. He boasts deep knowledge in Data Science and Machine Learning. Versed in Python, JavaScript, PHP, R, and Golang. Skilled in frameworks like Angular and React and platforms such as Node.js. His expertise spans both front-end and back-end development. His proficiency in the Python language stands as a testament to his versatility and commitment to the craft.
You need to cover observer pattern at a high level, subscriber models, multiple susbcription, caching scenarios, cold v hot, connectable observables, operators etc. In the cases you’ve outlined, manual unsubscription shouldn’t be needed and should be discouraged as correctly written finite observables should handle subscriber unsubscription internally and complete the observable. Hence why you don’t need to unubscribe from HttpClient observables.
Side note: From a purely angular 7 standpoint this entire post defies best practice. Was the angular 7 ref just for the SEO potential?
Isn’t this just Rxjs? What is Angular 7 has to do with Observables?
By reading the title, I thought Observables are now part of Angular version 7.
Yes, you are right, both are a totally different thing. The main motto of this example is that how we can use Angular with Observables and yes if you install angular then rxjs will be installed as well. So rxjs is kind of part of angular projects.
It could be helpful if you also provide a sample of unit tests for your class
it is helpful if you give a high level eg to use observables
it is helpful if you give a high level eg to use observables and to make in real time
This is the best easiest example for a beginner like me. To explain this high level, we need to first make sure that we are getting the basics right with the beginners.
I would be happier if you post one more basic working example for Observables, subscribe.
Thank you.
Hi,
I tried this example with one variable declared in generic utility class. this variable value is updated by different component in application. so my problem is, i want to listen this variable of custom interface type for eg activeFunctionDiagram: FunctionDiagram, so here activeFunctionDiagram is variable of type FunctionDiagram. how can i do this, any solution? one thing i tried is create observable on this variable, but i subscribe it in utility class constructor itself, it give me the first value of variable, not the different value, when other component change this variable value or simply update any one property of this variable.