In today’s fast-paced world where web development processes are changing day by day and applications are becoming more data-centric, it’s essential to utilize tools and frameworks that allow for efficient and reliable handling of asynchronous tasks.
In Angular, we generally use Observables to handle asynchronous operations. As they provide powerful features like cancellation, retry, and chaining multiple operations.
However, in some scenarios, we may need to use Promises where it can be more suitable. Promises are easier to understand and offer a simpler API for handling single asynchronous events.
In some cases, you may come across third-party libraries or APIs that return Promises, or you may need to integrate with non-Angular codebases that use Promises extensively. In these situations, understanding how to work with Promises in Angular becomes essential.
In this tutorial, we will explore how to use Promises in Angular, alongside Observables, to handle various use cases effectively.
Going forward, we will put light on how to use Promises to handle HTTP Rest API calls with error handling in Angular classes, as well as explore various use cases that developers may encounter when dealing with remote JSON data from HTTPS API calls.
[lwptoc]
What is Promise in Angular?
Promises in Angular represent an eventual completion or failure of an asynchronous operation and provide a value upon fulfilment. They provide a simple and consistent way to handle asynchronous operations, such as making HTTP requests or handling user input, without getting lost in a web of callbacks.
Basic Example of using Promise in TypeScript Class
To make an HTTP call using Promises in Angular, we need to import the HttpClient
module and inject it into our service or component. Here’s an example of making a simple GET request to an API endpoint:
import { HttpClient } from '@angular/common/http';
export class DataService {
constructor(private http: HttpClient) { }
getData() {
return this.http.get('https://api.example.com/data')
.toPromise()
.then(response => response)
.catch(error => console.error('An error occurred:', error));
}
}
In this example, we’re making a GET request to the ‘https://api.example.com/data‘ endpoint, converting the Observable
returned by http.get()
into a Promise
using the toPromise()
method, and then handling the response and error accordingly.
Error Handling
Error handling is a must when making HTTP requests, it allows us to gracefully handle situations where the API call may fails or returns an error. In the previous example, we used the catch()
method to log the error to the console.
We can also use a custom error-handling function to provide more detailed information or even retry the request if necessary.
handleError(error: any): void {
console.error('An error occurred:', error);
// Add custom error handling logic here
}
getData() {
return this.http.get('https://api.example.com/data')
.toPromise()
.then(response => response)
.catch(this.handleError);
}
Multiple HTTP Calls
There are situations where multiple HTTP calls are required, and we want to execute them in parallel or sequentially.
To achieve this, we can use Promise.all()
and Promise.allSettled()
for parallel execution, or chain multiple promises using then()
for sequential execution.
// Parallel Execution
Promise.all([
this.http.get("https://api.example.com/data1").toPromise(),
this.http.get("https://api.example.com/data2").toPromise(),
])
.then(([response1, response2]) => {
// Handle responses
})
.catch(this.handleError);
// Sequential Execution
this.http
.get("https://api.example.com/data1")
.toPromise()
.then((response1) => {
// Handle response1
return this.http.get("https://api.example.com/data2").toPromise();
})
.then((response2) => {
// Handle response2
})
.catch(this.handleError);
Chaining Promises
In some cases, we may need to chain multiple promises to handle dependent operations. For instance, we might need to fetch data from one endpoint, process it, and then send the processed data to another endpoint. Here‘s an example of how to chain promises in Angular:
fetchData() {
return this.http.get('https://api.example.com/data').toPromise();
}
processData(data: any) {
// Process data and return the result
}
submitData(processedData: any) {
return this.http.post('https://api.example.com/submit', processedData).toPromise();
}
getDataAndSubmit() {
this.fetchData()
.then(data => this.processData(data))
.then(processedData => this.submitData(processedData))
.catch(this.handleError);
}
How to use async/await with Angular Promises?
We can also use async/await with Angular Promises. The async/await syntax provides a cleaner and more readable way to handle asynchronous operations using Promises. Here’s an example:
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
apiUrl = 'https://jsonplaceholder.typicode.com/comments';
constructor(private http: HttpClient) { }
async ngOnInit() {
try {
const comments = await this.fetchComments();
console.log('Comments:', comments);
} catch (error) {
console.error('Request failed with this error:', error);
}
}
fetchComments() {
return this.http.get(this.apiUrl).toPromise();
}
}
In the example above, we made the ngOnInit()
method as async
. Inside this method, we use await
to fetch comments by calling the fetchComments()
function, which returns a Promise. The await
keyword waits for the Promise to resolve or reject, which will make it easier to handle success or error cases.
How can I cancel an HTTP request made with Angular Promises?
Cancelling an HTTP request made with Angular Promises is not as straightforward as with Observables, because Promises don’t have built-in support for cancellation. But, we can achieve this by using an AbortController
and a button click event. Here’s an example:
First, update the app.component.html
file to include a button to trigger the cancellation:
<button (click)="cancelRequest()">Cancel Request</button>
Modify the app.component.ts
file to use the AbortController
and handle the cancellation:
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
apiUrl = 'https://jsonplaceholder.typicode.com/posts';
abortController: AbortController;
constructor(private http: HttpClient) { }
ngOnInit() {
this.getPost(1)
.then((post) => {
console.log('Post:', post);
})
.catch((error) => {
if (error.name === 'AbortError') {
console.log('Request canceled');
} else {
console.error('Request failed with this error:', error);
}
});
}
getPost(id: number) {
const url = `${this.apiUrl}/${id}`;
this.abortController = new AbortController();
const requestOptions = {
signal: this.abortController.signal
};
return this.http.get(url, requestOptions).toPromise();
}
cancelRequest() {
if (this.abortController) {
this.abortController.abort();
}
}
}
In this example, we added an AbortController
instance and assigned it to the abortController
property. We then passed the signal
property of the AbortController
to the HTTP request options.
When the user clicks the “Cancel Request” button, the cancelRequest()
function is called, which aborts the request using the abort()
method of the AbortController
.
If the request is cancelled, the catch block will receive an error with the name ‘AbortError’, which can be hanlded accordingly.
Conclusion
In this article, we’ve covered the basics of using Angular 15 Promises to handle HTTP Rest API calls with error handling and also discussed various use cases while dealing with remote JSON data from HTTPS API calls. Hope this was helpful.
Leave a Reply