Table of contents
1.
Introduction
2.
Promise
2.1.
Key Features of Promises
2.2.
Syntax
3.
How Promises Work  
4.
Using Promises in Angular  
5.
Approach
5.1.
1. Identify Asynchronous Tasks
5.2.
2. Wrap the Asynchronous Task in a Promise
5.3.
3. Handle Results
6.
Disadvantages of Promises
7.
Example
7.1.
Example:
8.
How to Define Our Own Promises?
8.1.
Example
9.
Future of Promises in Angular
10.
Frequently Asked Questions
10.1.
What are Promises used for in Angular?
10.2.
How do Promises differ from Observables?
10.3.
Can I still use Promises in Angular?
11.
Conclusion
Last Updated: Jan 26, 2025
Easy

What are Promises in Angular?

Author Gaurav Gandhi
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Promises are an essential concept in Angular and JavaScript, used to handle asynchronous operations like API calls or fetching data. They make code execution more manageable and prevent callback-related issues. 

What are Promises in Angular?

In this article, we will discuss what Promises are, their syntax, how to use them effectively, their drawbacks, and how they fit into the future of Angular development. 

Promise

Promise is an object in JavaScript that represents the eventual completion or failure of an asynchronous operation. It allows you to handle the success or failure of an operation using .then(), .catch(), and .finally() methods. Promises help streamline asynchronous code, avoiding deeply nested callbacks (known as callback hell).

Key Features of Promises

  1. A Promise has three states:
    • Pending: The initial state, neither fulfilled nor rejected.
       
    • Fulfilled: The operation was successful.
       
    • Rejected: The operation failed.
       
  2. Once a Promise is resolved (fulfilled or rejected), it cannot be changed.

Syntax

Here is the basic syntax for creating a Promise in JavaScript:

const promise = new Promise((resolve, reject) => {
    // Asynchronous operation
    let success = true;


    if (success) {
        resolve('Operation succeeded');
    } else {
        reject('Operation failed');
    }
});
// Handling the result
promise
    .then(result => console.log(result))
    .catch(error => console.log(error))
    .finally(() => console.log('Operation complete'));

Explanation:

  1. new Promise: Creates a Promise object.
     
  2. resolve: Indicates the operation succeeded.
     
  3. reject: Indicates the operation failed.
     
  4. .then(): Executes when the Promise is fulfilled.
     
  5. .catch(): Executes when the Promise is rejected.
     
  6. .finally(): Executes regardless of the result.

How Promises Work  

A promise is an object that represents the eventual completion or failure of an asynchronous operation. It has three states:  

1. Pending: The initial state, where the operation is still ongoing.  
 

2. Fulfilled: The operation completed successfully, & the promise returns a value.  
 

3. Rejected: The operation failed, & the promise returns an error.  


Promises are created using the `Promise` constructor, which takes a function with two arguments: `resolve` & `reject`. The `resolve` function is called when the operation succeeds, & the `reject` function is called when it fails.  

Let’s take a basic example of how a promise works:  

// Creating a promise
let myPromise = new Promise((resolve, reject) => {
  let success = true; // Simulating a condition


  if (success) {
    resolve("Operation successful!"); // Resolve the promise
  } else {
    reject("Operation failed!"); // Reject the promise
  }
});

// Handling the promise
myPromise
  .then((result) => {
    console.log(result); // Output: Operation successful!
  })
  .catch((error) => {
    console.log(error); // Output: Operation failed!
  });


In this example:  

  • We create a promise using the `Promise` constructor.  
     
  • Inside the promise, we simulate a condition (`success`) to decide whether to call `resolve` or `reject`.  
     
  • We use `.then()` to handle the resolved value & `.catch()` to handle any errors.  
     

Promises are chainable, meaning you can link multiple `.then()` calls to perform sequential operations. For example:  

myPromise
  .then((result) => {
    console.log(result); // Output: Operation successful!
    return "Next step"; // Return a value for the next .then()
  })
  .then((nextResult) => {
    console.log(nextResult); // Output: Next step
  })
  .catch((error) => {
    console.log(error); // Handle errors
  });


This chaining allows you to perform a series of asynchronous tasks in a clean & readable way.  

Using Promises in Angular  

In Angular, promises are often used to handle asynchronous operations like HTTP requests. While Angular primarily uses Observables (via RxJS) for handling async tasks, promises are still relevant, especially when working with third-party libraries or legacy code.  

Let’s take an example of how to use promises in Angular to fetch data from an API.  

Step 1: Set Up an Angular Service  

First, create a service to handle the HTTP request. Angular’s `HttpClient` module is used to make HTTP calls.  

ng generate service data


This command generates a service file named `data.service.ts`.  


Step 2: Import HttpClientModule  

In your `app.module.ts`, import `HttpClientModule` to enable HTTP functionality.  

import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    // Your components
  ],
  imports: [
    BrowserModule,
    HttpClientModule, // Add this line
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}


Step 3: Create a Method to Fetch Data Using Promises  

In the `data.service.ts` file, create a method that uses `HttpClient` to fetch data & returns a promise.  

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root',
})
export class DataService {
  private apiUrl = 'https://jsonplaceholder.typicode.com/posts'; // Example API

  constructor(private http: HttpClient) {}

  // Method to fetch data using a promise
  fetchData(): Promise<any> {
    return this.http.get(this.apiUrl).toPromise();
  }
}


Here, we use the `.toPromise()` method to convert the observable returned by `http.get()` into a promise.  


Step 4: Use the Service in a Component  

Now, let’s use the `fetchData()` method in a component to display the fetched data.  

import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-root',
  template: `
    <h1>Posts</h1>
    <ul>
      <li ngFor="let post of posts">{{ post.title }}</li>
    </ul>
  `,
})
export class AppComponent implements OnInit {
  posts: any[] = [];

  constructor(private dataService: DataService) {}

  ngOnInit() {
    this.dataService
      .fetchData()
      .then((data) => {
        this.posts = data; // Assign fetched data to posts
      })
      .catch((error) => {
        console.error('Error fetching data:', error);
      });
  }
}


In this example:  

  • We call the `fetchData()` method in the `ngOnInit()` lifecycle hook.  
     
  • When the promise resolves, the data is assigned to the `posts` array, which is displayed in the template using `ngFor`.  
     
  • If the promise is rejected, the error is logged to the console.  
     

Step 5: Run the Application  

Run your Angular application using:  

ng serve


Open your browser & navigate to `http://localhost:4200`. You should see a list of post titles fetched from the API.  

This example shows how to use promises in Angular to handle asynchronous HTTP requests. While Angular encourages the use of observables, promises are still a valid & useful tool in certain scenarios.  

Approach

To use Promises effectively in Angular applications, follow these steps:

1. Identify Asynchronous Tasks

Determine operations like HTTP requests, timers, or other delayed tasks that require asynchronous handling.

2. Wrap the Asynchronous Task in a Promise

Use the new Promise constructor to manage the task’s success or failure.

3. Handle Results

Chain .then(), .catch(), and .finally() to process the results of the asynchronous task.

Disadvantages of Promises

While Promises simplify asynchronous programming, they have some drawbacks:

  1. Chaining Can Get Complex: Long chains of .then() can become hard to read and maintain.
     
  2. Error Handling: If not handled carefully, errors can propagate incorrectly.
     
  3. Cannot Cancel: Promises cannot be canceled once started.
     
  4. Compatibility Issues: Older browsers may require polyfills for Promise support.

Example

Below is an example of using Promises in Angular to fetch data from an API:

Example:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-promise-demo',
  template: `<div *ngIf="data">{{ data }}</div>`
})
export class PromiseDemoComponent implements OnInit {
  data: string;

  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    this.fetchData()
      .then(response => {
        this.data = response;
        console.log('Data fetched successfully:', response);
      })
      .catch(error => {
        console.error('Error fetching data:', error);
      });
  }

  fetchData(): Promise<string> {
    return new Promise((resolve, reject) => {
      this.http.get<string>('https://api.example.com/data').subscribe(
        response => resolve(response),
        error => reject(error)
      );
    });
  }
}

Output:

When the API call is successful, the fetched data is displayed in the component. Otherwise, an error message is logged to the console.

How to Define Our Own Promises?

Creating your own Promises is simple. Here's a step-by-step example:

Example

function customPromiseExample(value) {
  return new Promise((resolve, reject) => {
    if (value) {
      resolve('Promise resolved with value: ' + value);
    } else {
      reject('Promise rejected due to invalid value');
    }
  });
}
customPromiseExample('Hello, World!')
  .then(response => console.log(response))
  .catch(error => console.log(error));

Explanation:

  1. The function customPromiseExample accepts a value.
     
  2. It resolves the Promise if the value is valid.
     
  3. It rejects the Promise otherwise.
     

Output:

Promise resolved with value: Hello, World!

Future of Promises in Angular

Although Promises are widely used, Angular promotes using Observables (from RxJS) for most asynchronous operations. Observables offer more features than Promises, such as:

  1. Cancellation: You can unsubscribe from Observables to stop ongoing operations.
     
  2. Multiple Values: Observables can emit multiple values over time, unlike Promises, which resolve once.
     
  3. Integration with Angular: Angular’s HTTPClient and other modules use Observables by default.

Frequently Asked Questions

What are Promises used for in Angular?

Promises handle asynchronous operations, such as fetching data from an API or waiting for a task to complete.

How do Promises differ from Observables?

Promises resolve or reject a single value, while Observables can emit multiple values over time and support cancellation.

Can I still use Promises in Angular?

Yes, you can use Promises in Angular, but Observables are the preferred choice for most asynchronous tasks.

Conclusion

In this article, we discussed Promises in Angular, their syntax, and how to use them effectively for asynchronous programming. We also explained their advantages, disadvantages, and how to define custom Promises. While Promises are still relevant, Observables are becoming the standard for handling complex asynchronous tasks in Angular. 

Live masterclass