Voiced by Amazon Polly |
Introduction
Handling asynchronous operations is a core part of JavaScript development and promises an elegant way to manage these. Before promises, developers often used callback functions to manage asynchronous tasks, which could lead to confusing and deeply nested structures, commonly called “callback hell.” Promises to streamline this process by providing a more readable and structured approach to handle asynchronous code.
In this guide, we’ll dive into promises, how they work, and how you can use them effectively in your code.
Pioneers in Cloud Consulting & Migration Services
- Reduced infrastructural costs
- Accelerated application deployment
What is a Promise in JavaScript?
A Promise is an object representing an asynchronous operation’s eventual completion (or failure). When an operation begins, the promise is in a “pending” state and will eventually transition to either:
- Fulfilled: The operation was completed successfully.
- Rejected: The operation failed.
Once a promise settles (either fulfilled or rejected), it cannot change its state again.
The Anatomy of a Promise
To understand how promises work, let’s look at the structure of a simple promise:
1 2 3 4 5 6 7 8 9 10 11 |
const myPromise = new Promise((resolve, reject) => { let operationSuccess = true; setTimeout(() => { if (operationSuccess) { resolve("Operation was successful!"); } else { reject("Operation failed."); } }, 2000); }); |
Here’s what’s happening:
- A new Promise object is created, and it takes an executor function with two parameters: resolve and reject.
- If the operation succeeds (simulated by operationSuccess), resolve is called, which transitions the promise to the fulfilled state.
- If the operation fails, reject is invoked, putting the promise into the rejected state.
Handling a Promise's Result
Once a promise is created, it’s important to handle its result using .then() for a successful outcome and .catch() for errors.
1 2 3 4 5 6 7 |
myPromise .then((result) => { console.log(result); // logs: "Operation was successful!" }) .catch((error) => { console.error(error); // In case of rejection, this would log the error message. }); |
- then(): Handles the result of the promise when it resolves successfully. It takes a callback function that gets executed with the resolved value.
- catch(): Handles the error in case the promise is rejected.
These methods allow you to effectively manage successful and failed outcomes of asynchronous tasks.
Promise Chaining
One of the key benefits of promises is that they allow you to chain multiple asynchronous operations together in a clean and readable way. This avoids the deeply nested structures common with callbacks.
For example, if you need to perform a series of asynchronous operations where each step depends on the previous one, you can chain .then() calls:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
const fetchData = new Promise((resolve) => { setTimeout(() => resolve("Data fetched"), 1000); }); fetchData .then((data) => { console.log(data); // "Data fetched" return new Promise((resolve) => setTimeout(() => resolve("Processing data"), 1000)); }) .then((processedData) => { console.log(processedData); // "Processing data" return "Final step completed"; }) .then((finalMessage) => { console.log(finalMessage); // "Final step completed" }) .catch((error) => { console.error("An error occurred:", error); }); |
Each .then() passes its resolved value to the next .then() in the chain, allowing asynchronous tasks to run sequentially.
Promise Methods: Promise.all() and Promise.race()
JavaScript promises also come with utility methods that allow you to manage multiple promises at once:
- Promise.all()
Promise.all() runs multiple promises concurrently and waits for all of them to either resolve or for one to reject. If any promises are rejected, Promise.all() rejects immediately with the first error.
1 2 3 4 5 6 7 8 9 10 11 |
const promise1 = new Promise((resolve) => setTimeout(() => resolve("First promise"), 1000)); const promise2 = new Promise((resolve) => setTimeout(() => resolve("Second promise"), 2000)); const promise3 = new Promise((resolve, reject) => setTimeout(() => reject("Third promise failed"), 3000)); Promise.all([promise1, promise2, promise3]) .then((results) => { console.log(results); // Won't be logged if any promise fails }) .catch((error) => { console.error("Error:", error); // Logs "Third promise failed" }); |
In this case, the failure of any single promise (e.g., promise3) causes the whole operation to fail.
- Promise.race()
Promise.race() also runs multiple promises concurrently but resolves or rejects as soon as one promise settles (whether resolved or rejected).
1 2 3 4 5 6 7 8 9 10 |
const slowPromise = new Promise((resolve) => setTimeout(() => resolve("Slow response"), 3000)); const fastPromise = new Promise((resolve) => setTimeout(() => resolve("Fast response"), 1000)); Promise.race([slowPromise, fastPromise]) .then((result) => { console.log(result); // Logs "Fast response" }) .catch((error) => { console.error("Error:", error); }); |
In this example, Promise.race() resolves as soon as the fastPromise settles, ignoring the slower promise.
Promises and async/await
Although promises provide a cleaner way to handle asynchronous operations, async/await takes it further by making asynchronous code look synchronous. It’s syntactic sugar over promises and is often more intuitive.
Here’s how the earlier example can be rewritten using async/await:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
async function fetchData() { try { const data = await fetchDataPromise(); console.log(data); // "Data fetched" const processedData = await processDataPromise(data); console.log(processedData); // "Processing data" console.log("Final step completed"); } catch (error) { console.error("Error occurred:", error); } } fetchData(); |
The await keyword pauses the execution of the async function until the promise is resolved or rejected, simplifying how you manage asynchronous code.
Conclusion
With methods like .then(), .catch(), and .finally(), promises offer flexibility in controlling the outcomes of operations, while utility functions like Promise.all() and Promise.race() allow for concurrent execution of multiple promises.
Drop a query if you have any questions regarding JavaScript promises and we will get back to you quickly.
Making IT Networks Enterprise-ready – Cloud Management Services
- Accelerated cloud migration
- End-to-end view of the cloud environment
About CloudThat
CloudThat is a leading provider of Cloud Training and Consulting services with a global presence in India, the USA, Asia, Europe, and Africa. Specializing in AWS, Microsoft Azure, GCP, VMware, Databricks, and more, the company serves mid-market and enterprise clients, offering comprehensive expertise in Cloud Migration, Data Platforms, DevOps, IoT, AI/ML, and more.
CloudThat is the first Indian Company to win the prestigious Microsoft Partner 2024 Award and is recognized as a top-tier partner with AWS and Microsoft, including the prestigious ‘Think Big’ partner award from AWS and the Microsoft Superstars FY 2023 award in Asia & India. Having trained 650k+ professionals in 500+ cloud certifications and completed 300+ consulting projects globally, CloudThat is an official AWS Advanced Consulting Partner, Microsoft Gold Partner, AWS Training Partner, AWS Migration Partner, AWS Data and Analytics Partner, AWS DevOps Competency Partner, AWS GenAI Competency Partner, Amazon QuickSight Service Delivery Partner, Amazon EKS Service Delivery Partner, AWS Microsoft Workload Partners, Amazon EC2 Service Delivery Partner, Amazon ECS Service Delivery Partner, AWS Glue Service Delivery Partner, Amazon Redshift Service Delivery Partner, AWS Control Tower Service Delivery Partner, AWS WAF Service Delivery Partner and many more.
To get started, go through our Consultancy page and Managed Services Package, CloudThat’s offerings.
FAQs
1. What is the difference between a callback and a promise?
ANS: – A callback is a function passed as an argument to another function, often used for handling asynchronous operations. However, callbacks can lead to nested and hard-to-read code (callback hell). A promise provides a cleaner, more readable approach to handling asynchronous tasks by allowing chaining and better error handling. It can either resolve (successful completion) or reject (failure).
2. Can a promise be resolved or rejected more than once?
ANS: – No, a promise can only be settled (resolved or rejected) once. After that, its state is immutable, meaning it cannot be changed again.
WRITTEN BY Subramanya Datta
Click to Comment