Promises in Angular: Secret to Building Non-Blocking Apps That Don’t Freeze!
Updated on Jun 30, 2025 | 13 min read | 21.05K+ views
Share:
For working professionals
For fresh graduates
More
Updated on Jun 30, 2025 | 13 min read | 21.05K+ views
Share:
Table of Contents
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 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:
Promises in Angular has these states:
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.
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.
These are the three core methods used to handle Promise results in JavaScript:
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)
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)
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
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
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
Also Read: Angular Vs AngularJs: Difference Between Angular & AngularJS
Next, let’s look at how you can define your own promises in Angular.
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:
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.
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:
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:
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:
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:
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:
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:
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.
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
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
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
Top Resources