View All
View All
View All
View All
View All
View All
View All
View All
View All
View All
View All

Promises in Angular: Secret to Building Non-Blocking Apps That Don’t Freeze!

By Pavan Vadapalli

Updated on Jun 30, 2025 | 13 min read | 21.05K+ views

Share:

Did You Know? A Promise in Angular can resolve asynchronous operations, like HTTP requests, in as little as a single line of code. This allows developers to handle thousands of non-blocking tasks without freezing the user interface.

Promises in Angular are JavaScript objects representing the eventual completion of asynchronous operations, acting as contracts that guarantee responses without blocking the user interface. 

In e-commerce applications, when users search for products, Promises allow Angular's HttpClient to fetch API data while displaying loading spinners and maintaining responsiveness. They handle success scenarios, failures, and complex operation chaining. This ensures smooth user experiences rather than frozen interfaces during data retrieval.

This guide covers what are promises in Angular, its syntax, usage, and real-world examples to help you build responsive, non-blocking applications.

Want to learn how to use programming tools and techniques efficiently for better outcomes? Join upGrad’s Online Software Development Courses and work on hands-on projects that simulate real industry scenarios. 

Promises in Angular: Features and Syntax

Promises in Angular are class-based objects created using the new keyword that handles asynchronous operations. It's defined by passing an executor function to the Promise constructor, which takes two parameters: resolve (for success) and reject (for errors). The executor function contains your async operation, and these handlers manage the eventual result or failure.

In 2025, businesses are looking for developers who can build fast, non-blocking apps with tools like Angular. But if you're feeling a little behind, don't worry – there are courses that can help. Here are some options to get you up to speed:

Key Features of Promises in Angular:

  • Non-blocking execution - Keeps UI responsive during async operations 
  • Built-in error handling - Automatic success/failure state management
  • Method chaining - Chain operations with .then() and .catch()
  • Single resolution - Resolves once with either success or failure
  • Clean syntax - Eliminates callback hell with readable code structure

Promises in Angular has these states: 

  • Pending: This is an initial state, which is neither fulfilled nor rejected. 
  • Fulfilled: This means that the operation is completed successfully. 
  • Rejected: This means that the operation has failed. 

A promise in Angular is said to be settled if it is either fulfilled or rejected. It cannot be in pending state. 

Also Read: 28 Angular Projects in 2025: Beginner to Advanced Ideas + Source Code

Syntax of Promises in Angular:

const myPromise = new Promise((resolve, reject) => { 
    setTimeout(() => { 
          resolve('this is a promise'); 
    }, 300); 
}); 
myPromise.then((value) => { 
     console.log(value); 
      // expected output: "this is a promise" 
}); 
console.log(promise1); 
// expected output: [object Promise]

Explanation: This code creates a Promise that resolves with "this is a promise" after 300ms using setTimeout(). The output shows [object Promise] first (immediate synchronous log), then "this is a promise" after the delay when .then() executes, demonstrating asynchronous execution where the Promise object displays before its resolved value.

Output:

[object Promise]

this is a promise

Promise objects have a .then and a .catch methods which handle fulfilled results and errors if any occurred. They receive the outcome of async operations as data or error from the resolve and reject handler in the promise constructor. 

Also Read: Directives in Angular Explained with Example

Now that you know what are promises in Angular, let’s look at some key methods of executing promises in Angular.

Core Methods of Executing Promises in Angular

The core methods for executing and managing promises include .then() for handling successful resolutions, .catch() for managing errors, and .finally() for executing cleanup actions after a promise settles, regardless of the outcome. 

By chaining these methods, Angular developers can write clear, readable code that efficiently manages complex asynchronous logic, ensures robust error handling, and maintains responsive user interfaces even during long-running operations.

Coverage of AWS, Microsoft Azure and GCP services

Certification8 Months

Job-Linked Program

Bootcamp36 Weeks

These are the three core methods used to handle Promise results in JavaScript:

1. .then()

Executes when a Promise resolves successfully, receiving the resolved value as its callback parameter. It runs immediately after resolve() is called with the result.

Sample Code:

const successPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('Data fetched successfully!');
    }, 1000);
});

successPromise.then((result) => {
    console.log(result);
});

Explanation: The .then() method executes when the Promise resolves, receiving "Data fetched successfully!" as the result parameter and logging it.

Output: Data fetched successfully! (after 1 second) 

2. .catch()

Executes when a Promise is rejected, running immediately after reject() is called. It handles errors and failures in the Promise chain.

Sample Code:

const failPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('Network error occurred!');
    }, 1000);
});

failPromise.catch((error) => {
    console.log('Error:', error);
});

Explanation: The .catch() method executes when the Promise rejects, receiving the error message and handling it gracefully.

Output: Error: Network error occurred! (after 1 second)

3. .finally()

Always executes regardless of whether the Promise resolves or rejects. It runs after the Promise "settles" (completes in any state) and is used for cleanup operations like hiding loading spinners.

Sample Code:

const apiCall = new Promise((resolve, reject) => {
    Math.random() > 0.5 ? resolve('Success!') : reject('Failed!');
});

apiCall
    .then(result => console.log(result))
    .catch(error => console.log('Error:', error))
    .finally(() => console.log('API call completed'))

Explanation: .finally() always runs regardless of success or failure, perfect for cleanup operations like hiding loading indicators.

Output: Either Success! or Error: Failed! followed by API call completed

Method Chaining: Since .then() and .catch() return new Promises, they can be chained together, allowing you to create sequences of asynchronous operations and handle multiple success/error scenarios in a clean, readable way.

Also Read: Life Cycle of Angular Components: Various Methods Explained

Example of Promises in Angular

This example demonstrates a complete Promise lifecycle with all three handler methods. The Promise simulates a conditional asynchronous operation using setTimeout() to wait 2 seconds before evaluating a simple condition.

Since the count variable is hardcoded to 5, the Promise will always resolve successfully with "done", triggering the .then() handler to log the result, while the .catch() handler remains unused. The .finally() handler executes regardless, providing cleanup functionality that runs after the Promise settles.

To demonstrate the use of Promises in angular let us see an example using Promises:

promise = new Promise((resolve, reject)=>{ 
      setTimeout(()=>{ 
            let count = 5 
      if(count == 5){ 
            resolve("done") 
      }else{ 
            reject(new Error("Ooops something went wrong)) 
      } 
    }, 2000) 
} ) 
Promise 
.then((result)=>{ 
      console.log(result) 
}) 
.catch((error)=>{ 
      console.log(error) 
}) 
.finally(()=>{ 
      console.log("Everything is finalized") 
})

Explanation: This Promise waits 2 seconds, then checks if count equals 5. Since count is set to 5, the condition if(count == 5) is true, so resolve("done") is called. The .then() method executes and logs "done", followed by .finally() which always runs and logs "Everything is finalized". The .catch() method doesn't execute because the Promise resolved successfully.

Output:

done

Everything is finalized

Solution: The conditional if statement evaluates to true because count = = 5. resolve(done) is then called and the value “done” is passed onto .then as a result. Hence “done” is logged onto the console. .finally is then executed and logs “Everything is finalized” to the console. 

Also Read: Easy Steps to Launch Your Angular Project Successfully

Chaining Promises in Angular

There is a prevailing need to execute two or more asynchronous operations next to next sequentially, where each next operation starts when the previous operation succeeds, with the result from the prior operation. We manage this by designing a promise chain. 

In other words, after producing code performs a task and gets the result, we usually want to do something different with that result. But we cannot directly access that result. We have to use .then method. The .then method returns a new promise, different from the original promise:

const myPromise = doSomeAction(); 
const myPromise2 = promise.then(succeedCallback, failedCallback);

This second promise(myPromise2) represents the completion of doSomeAction as well as the completion of succeedCallback and failedCallback we passed in, which can be other async functions returning a promise. When it happens, any callbacks added to myPromise2 get in line behind the promise returned by either succeedCallback or failedCallback. 

Basically, each promise in angular represents the completion of another async step in the chain of promises.  

For example:

taskOne() 
  .then(function (result) { 
    return taskTwo(result); 
  }) 
  .then(function (newResult) { 
    return taskThree(newResult); 
  }) 
  .then(function (lastResult) { 
    console.log(`Receive the last result: ${lastResult}`); 
  }) 
  .catch(failureCallback);

Chaining After a Catch: 

After catching an error, it is also possible to chain. That means .catch method is useful to achieve new actions even after an action failed in chain, we can accomplish remaining actions without any error. 

For example:

new Promise((resolve, reject) => { 
  console.log("Start"); 
 
  resolve(); 
}) 
  .then(() => { 
    throw new Error("Something has failed"); 
 
    console.log("Do this action1"); 
  }) 
  .catch(() => { 
    console.error("Do this action2"); 
  }) 
  .then(() => { 
    console.log("Do this action compulsory without looking what happened at previous"); 
  });

Output:

Start

Do this action2

Do this action compulsory without looking what happened at previous

If you want to build a higher-level understanding of Javascript, upGrad’s Advanced Javascript for All course is what you need. Learn about prototypes, scopes, classes, modules, async programming, and more to enhance your web development skills and become a proficient JS developer.

Also Read: Angular Vs AngularJs: Difference Between Angular & AngularJS

Next, let’s look at how you can define your own promises in Angular.

How to Define Your Own Custom Promise Class?

Building a custom Promise class provides deep insight into JavaScript's asynchronous architecture and helps you understand the state management, callback queuing, and execution flow that make Promises so powerful for handling async operations.

Core Promise Properties:

Every Promise operates on a finite state machine with three possible states:
const STATE = {
    PENDING: 'PENDING',       // Initial state - operation not completed
    FULFILLED: 'FULFILLED',   // Success state - operation completed successfully  
    REJECTED: 'REJECTED'      // Error state - operation failed
}

Complete Promise Class Implementation:

class myPromise {
    constructor(callback) {
        // Initialize Promise properties
        this.state = STATE.PENDING;    // Current Promise state
        this.value = undefined;        // Stores resolved/rejected value
        this.handlers = [];            // Stores .then, .catch, .finally callbacks
        
        // Execute the callback immediately with resolve/reject methods
        try {
            callback(this._resolve, this._reject);
        } catch(err) {
            this._reject(err);
        }
    }
    
    _resolve = (value) => {
        if (this.state === STATE.PENDING) {
            this.state = STATE.FULFILLED;
            this.value = value;
            this._executeHandlers();
        }
    }
    
    _reject = (error) => {
        if (this.state === STATE.PENDING) {
            this.state = STATE.REJECTED;
            this.value = error;
            this._executeHandlers();
        }
    }
    
    _executeHandlers() {
        this.handlers.forEach(handler => {
            if (this.state === STATE.FULFILLED && handler.onSuccess) {
                handler.onSuccess(this.value);
            } else if (this.state === STATE.REJECTED && handler.onFailure) {
                handler.onFailure(this.value);
            }
        });
    }
    
    then(onSuccess, onFailure) {
        this.handlers.push({ onSuccess, onFailure });
        if (this.state !== STATE.PENDING) {
            this._executeHandlers();
        }
        return this;
    }
    
    catch(onFailure) {
        return this.then(null, onFailure);
    }
    
    finally(callback) {
        this.handlers.push({ 
            onSuccess: callback, 
            onFailure: callback 
        });
        if (this.state !== STATE.PENDING) {
            callback();
        }
        return this;
    }
}

Usage Example with Output:

// Test successful Promise

const successPromise = new myPromise((resolve, reject) => {

    setTimeout(() => {

        resolve("Custom Promise resolved!");

    }, 1000);

});

successPromise

    .then(result => console.log("Success:", result))

    .catch(error => console.log("Error:", error))

    .finally(() => console.log("Custom Promise completed"));

// Test failed Promise

const failPromise = new myPromise((resolve, reject) => {

    setTimeout(() => {

        reject("Custom Promise failed!");

    }, 1500);

});

failPromise

    .then(result => console.log("Success:", result))

    .catch(error => console.log("Error:", error))

    .finally(() => console.log("Failed Promise completed"));

Code Explanation:

  1. Constructor: Immediately executes the callback with custom _resolve and _reject methods, initializing state as PENDING
  2. State Transition: _resolve and _reject change state only from PENDING, preventing multiple resolutions
  3. Handler Queue: The handlers array stores callbacks until the Promise settles, then executes them via _executeHandlers()
  4. Method Chaining: Each method returns this, enabling chaining like native Promises
  5. Immediate vs Deferred: If Promise is already settled when .then() is called, handlers execute immediately

Expected Output:

Success: Custom Promise resolved!

Custom Promise completed

Error: Custom Promise failed!

Failed Promise completed

This implementation demonstrates how Promises maintain state consistency, queue callbacks, and provide the foundation for modern JavaScript's asynchronous programming model.

If you want to improve your knowledge of object-oriented programming, upGrad’s Java Object-oriented Programming can help you. Learn classes, objects, inheritance, polymorphism, encapsulation, and abstraction with practical programming examples.

Also Read: A Quick Guide to Build and Publish Angular Library in 2025

Next, let’s look at some of the future development of promises in Angular.

What is The Future of Promises in Angular?

While Angular has largely transitioned to RxJS Observables for most HTTP operations, Promises continue to play a crucial role in specific scenarios and will remain relevant in Angular's ecosystem.

Here's why Promises maintain their importance and where they excel:

1. Single HTTP Requests and Simple Async Operations 

Promises are perfect for one-time operations like user authentication or configuration loading. When you need a simple API call that returns once, Promises provide cleaner syntax than Observables:

// Perfect use case for Promises
async loginUser(credentials) {
  const response = await this.http.post('/api/login', credentials).toPromise();
  return response.token;
}

Outcomes:

  • Eliminates subscription management overhead for single-use operations
  • Reduces memory leaks by automatically cleaning up after resolution
  • Provides cleaner error handling with try-catch blocks
  • Simplifies unit testing with straightforward async/await patterns
  • Improves code readability for developers unfamiliar with reactive programming

2. Integration with Third-Party Libraries

Many external libraries and browser APIs return Promises natively. Angular applications frequently need to integrate with payment gateways, geolocation services, or file upload libraries that use Promise-based APIs:

// Integrating with browser APIs
async getCurrentLocation() {
  const position = await new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(resolve, reject);
  });
  return { lat: position.coords.latitude, lng: position.coords.longitude };
}

Outcomes:

  • Seamless integration without complex Observable wrappers or conversion utilities
  • Maintains native API behavior and error handling mechanisms
  • Reduces bundle size by avoiding unnecessary RxJS operators
  • Faster development time with direct Promise-to-Promise communication
  • Better compatibility with legacy codebases and existing JavaScript libraries

3. Async/Await Support for Cleaner Code

Angular's TypeScript environment fully supports async/await syntax, making Promise-based code more readable than Observable chains for sequential operations:

// Clean sequential operations with async/await
async processUserData(userId) {
  const user = await this.userService.getUser(userId).toPromise();
  const profile = await this.profileService.getProfile(user.profileId).toPromise();
  const preferences = await this.settingsService.getPreferences(user.id).toPromise();
  return { user, profile, preferences };
}

Outcomes:

  • Eliminates nested subscription callbacks and complex operator chains
  • Provides linear, top-to-bottom code flow that's easier to debug
  • Simplifies error propagation with natural try-catch exception handling
  • Reduces cognitive load for developers transitioning from synchronous programming
  • Enables better IDE support with improved autocomplete and type inference

4. Component Lifecycle and Route Guards

Angular's route guards and component lifecycle hooks work seamlessly with Promises, especially for authentication checks and data preloading:

// Route guard using Promises
async canActivate(): Promise<boolean> {
  const isAuthenticated = await this.authService.checkAuthentication().toPromise();
  if (!isAuthenticated) {
    this.router.navigate(['/login']);
    return false;
  }
  return true;
}

Outcomes:

  • Provides built-in Angular framework support without additional configuration
  • Ensures proper component initialization order and data availability
  • Prevents race conditions in navigation and authentication flows
  • Simplifies conditional routing logic with clear boolean return values
  • Improves user experience with proper loading states and navigation blocking

5. Testing and Mocking Simplified

Promises offer simpler testing scenarios compared to Observables when you need straightforward async behavior without complex stream operations:

// Easier unit testing with Promises
it('should authenticate user', async () => {
  const mockResponse = { token: 'abc123' };
  spyOn(service, 'login').and.returnValue(Promise.resolve(mockResponse));
  
  const result = await component.authenticateUser(credentials);
  expect(result.token).toBe('abc123');
});

Outcomes:

  • Eliminates complex testing utilities like fakeAsync and tick for simple scenarios
  • Provides straightforward mocking without Observable marble testing knowledge
  • Reduces test setup complexity and boilerplate code requirements
  • Enables faster test execution without subscription timing considerations
  • Improves test maintainability with cleaner assertion patterns and fewer async helpers

The Verdict: While Observables dominate Angular's reactive programming paradigm, Promises remain essential for specific use cases where single-value, one-time operations are needed. Their future in Angular lies in complementing Observables rather than replacing them, providing developers with the right tool for the right job.

Also Read: Angular Developer Salary in India: Insights, Key Factors, and Growth Strategies for 2025

Now, let’s dive into how upGrad can equip you with the skills to master Promises in Angular and take your app development capabilities to the next level.

How Can upGrad Help You Learn Angular?

Angular promises are a placeholder holding the result of an async operation. If the operation completes successfully, then the promise fulfills with the operation value, but if the operation fails, the promise rejects and becomes the reason for the failure. 

Understanding promises in Angular remains crucial in 2025 as they're still fundamental to JavaScript async programming and frequently used alongside Angular in real-world applications. This is where upGrad can help you. Its structured approach ensures you master practical skills needed for senior frontend, full-stack, and Angular specialist roles at top tech companies.

Along with the courses covered above, here are some additional programs that can help you in your learning journey:

If you're unsure where to begin or which area to focus on, upGrad’s expert career counselors can guide you based on your goals. You can also visit a nearby upGrad offline center to explore course options, get hands-on experience, and speak directly with mentors!

Boost your career with our popular Software Engineering courses, offering hands-on training and expert guidance to turn you into a skilled software developer.

Master in-demand Software Development skills like coding, system design, DevOps, and agile methodologies to excel in today’s competitive tech industry.

Stay informed with our widely-read Software Development articles, covering everything from coding techniques to the latest advancements in software engineering.

Reference:
https://www.fynd.academy/blog/promise-in-angular

Frequently Asked Questions (FAQs)

1. How do I handle promise rejection in Angular components without causing memory leaks when the component is destroyed?

2. Can I use Angular's dependency injection with promise-based services, and how does it affect performance compared to observable-based services?

3. What happens when I mix promises and Angular's change detection, especially with OnPush strategy?

4. How do I implement proper error boundaries for promise chains in Angular applications?

5. Is it possible to implement retry logic with exponential backoff for failed promises in Angular?

6. How can I test Angular components that heavily rely on promises without making actual HTTP calls?

7. What's the best way to convert legacy callback-based APIs to promises in Angular applications?

8. How do I handle concurrent promises efficiently in Angular without blocking the main thread?

9. Can I use Angular's HttpClient with promises instead of observables, and what are the trade-offs?

10. How do I implement promise-based state management patterns in Angular applications?

11. What's the proper way to handle promise timeouts in Angular applications, especially for critical user interactions?

Pavan Vadapalli

900 articles published

Director of Engineering @ upGrad. Motivated to leverage technology to solve problems. Seasoned leader for startups and fast moving orgs. Working on solving problems of scale and long term technology s...

Get Free Consultation

+91

By submitting, I accept the T&C and
Privacy Policy

India’s #1 Tech University

Executive PG Certification in AI-Powered Full Stack Development

77%

seats filled

View Program

Top Resources

Recommended Programs

upGrad

AWS | upGrad KnowledgeHut

AWS Certified Solutions Architect - Associate Training (SAA-C03)

69 Cloud Lab Simulations

Certification

32-Hr Training by Dustin Brimberry

upGrad

Microsoft | upGrad KnowledgeHut

Microsoft Azure Data Engineering Certification

Access Digital Learning Library

Certification

45 Hrs Live Expert-Led Training

upGrad

upGrad KnowledgeHut

Professional Certificate Program in UI/UX Design & Design Thinking

#1 Course for UI/UX Designers

Bootcamp

3 Months