Angular Observable
Observable
is an important concept in the RxJS library and is often used to handle asynchronous data streams. In Angular, Observable
is often used with HttpClient
to elegantly manage asynchronous data when processing HTTP requests.
What is Observable?
-
Definition:
Observable
is an object used to handle asynchronous events. It can be used to represent a value or event that may occur at a certain point in the future. -
Features
:
-
Delayed execution:
Observable
will not execute immediately, it will start executing when it is subscribed. -
Multiple emission values:
Observable
can emit values (data) multiple times in its life cycle, instead of only once like Promise. -
Support combination: The values of
Observable
can be combined and processed through a variety of operators provided by RxJS.
Example: HTTP Requests with Observable
Here is a detailed example of using Observable
in Angular, showing how to make GET and POST requests with HttpClient
.
1. Install RxJS and HttpClientModule
Angular applications have already integrated RxJS
by default, so there is no need to install it separately. Next, import HttpClientModule
in app.module.ts
:
// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http'; // Import HttpClientModule
import { FormsModule } from '@angular/forms'; // Import FormsModule
import { AppComponent } from './app.component';
import { DataService } from './data.service'; // Import custom service
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule, // Add HttpClientModule to the imports array
FormsModule // Add FormsModule to support two-way data binding
],
providers: [DataService], // Provide the custom service
bootstrap: [AppComponent]
})
export class AppModule { }
2. Create a data service
Create a service for sending HTTP requests:
ng generate service data
Add the following code to data.service.ts
:
// src/app/data.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root' // Makes the service available at the root level
})
export class DataService {
private apiUrl = 'https://jsonplaceholder.typicode.com/posts'; // Example API URL
constructor(private http: HttpClient) { }
// Send a GET request
getPosts(): Observable<any[]> {
return this.http.get<any[]>(this.apiUrl); // Returns an Observable
}
// Send a POST request
createPost(post: { title: string, body: string }): Observable<any> {
return this.http.post<any>(this.apiUrl, post); // Returns an Observable
}
}
3. Modify the root component
Use this service in the root component:
// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html', // Ensure HTML template file is used
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
posts: any[] = []; // Stores posts fetched from the API
newPost = { title: '', body: '' }; // For creating a new post
constructor(private dataService: DataService) { }
ngOnInit(): void {
// Fetch posts when the component initializes
this.dataService.getPosts().subscribe(data => {
this.posts = data; // Assign data to posts array
}, error => {
console.error('Request failed', error); // Handle errors
});
}
// Create a new post
createPost(): void {
this.dataService.createPost(this.newPost).subscribe(data => {
console.log('Post created', data);
this.posts.push(data); // Add the new post to the existing posts list
this.newPost = { title: '', body: '' }; // Reset input fields
}, error => {
console.error('Failed to create post', error); // Handle errors
});
}
}
4. Update HTML template
Update the template in src/app/app.component.html
as follows:
<h1>Posts</h1>
<ul>
<li *ngFor="let post of posts">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</li>
</ul>
<h2>Create Post</h2>
<div>
<input [(ngModel)]="newPost.title" placeholder="Title" />
<textarea [(ngModel)]="newPost.body" placeholder="Body"></textarea>
<button (click)="createPost()">Create</button>
</div>
5. Run the application
After ensuring everything is set up correctly, run in the project directory:
ng serve
Then visit http://localhost:4200
in your browser, you will see a list of post titles and can create a new post through the input box.
Summary
-
Use Observable: In the above example, both
getPosts
andcreatePost
methods returnObservable
types, which means they will not be executed immediately, but will start executing when subscribed. You can handle these asynchronous data by calling thesubscribe
method in the component. -
Asynchronous Programming:
Observable
provides a convenient way to handle asynchronous programming, making the code clearer and more maintainable.
Code Explanation
-
getPosts: Send a GET request to get a list of posts and return an
Observable
. -
createPost: Send a POST request to create a new post and return an
Observable
. -
subscribe: Subscribe to
Observable
to handle the returned data and errors.
By using Observable
, you can easily manage asynchronous data streams and implement more complex interaction logic in your application.