What the heck is Promise anyway?

Prajwal Bati
4 min readNov 25, 2024

Javascript is a popular language because of it’s fast execution and asynchronous behavior. Being a single threaded language, javascript is able to handle lots of requests because of it’s event driven architecture and how it handles asynchronous operations. Promise is a popular way of handling asynchronous operations in Javascript and today let me explain what really is the Promise and how it works.

A Promise in JavaScript is an object representing the eventual completion or failure of an asynchronous operation. Promises provide a cleaner way to manage asynchronous operations compared to traditional callback-based methods, addressing issues like callback hell and improving code readability and maintainability.

States of a Promise

A Promise has three states:

  1. Pending: The initial state, neither fulfilled nor rejected.
  2. Fulfilled (Resolved): The operation completed successfully, and the promise has a value.
  3. Rejected: The operation failed, and the promise has a reason (error).

Key Features of Promises

  • Chaining: Promises allow chaining of multiple asynchronous operations using .then() for readable sequential execution.
  • Error Handling: Errors can be captured in a .catch() block, simplifying debugging and error management.
  • Final Execution: The .finally() method lets you execute cleanup code after the promise settles (fulfilled or rejected). This is a optional function that can be used.

Creating a Promise

A promise is created using the Promise constructor, which takes a function with two parameters: resolve (to mark success) and reject (to mark failure). Generally, while working in real life projects, you might not need to create promise yourself. All the functions that deals with database will return promise and you will only need to handle the promise. But for the sake of learning, I will try to explain with the example.

const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true; // Simulate success or failure
success ? resolve("Data fetched!") : reject("Error fetching data.");
}, 1000);
});
};

// Using the Promise
fetchData()
.then((data) => console.log(data)) // Logs "Data fetched!" if resolved
.catch((error) => console.error(error)) // Logs "Error fetching data." if rejected
.finally(() => console.log("Operation complete"));

In the above snippet, the fetchData() function returns the promise. Function setTimeout() is a dummy used to simulate time consuming operation like calling the API. If the operation is successful, the resolve() function is called. This marks the promise as fulfilled, and the response is passed to the .then() function for further processing. If the operation fails, the reject() function is called. This marks the promise as rejected, and the error is passed to the .catch() function for error handling.

Static Methods of Promise

There are 6 static methods of Promise which can be used to manipulate promises. If you understand all these methods properly, then it will help you in your job when working with lots of promise functions.

1. Promise.resolve(value)

Creates a promise that is resolved with the given value. You can assign it as a value or as a function. Assigning as value or function will make difference when handling the promise as you can see below with parenthesis and without parenthesis.

const greetPromise = Promise.resolve("Hello");
greetPromise.then(data => console.log(data)); // Output: Hello

const greetAgain = () => Promise.resolve("Hello Again");
greetAgain().then(data => console.log(data)); // Output: Hello Again

2. Promise.reject(reason)

Creates a promise that is rejected with the given reason.

const rejectedPromise = Promise.reject("Rejected!");
rejectedPromise.catch(console.error); // Output: Rejected!

3. Promise.all(iterable)

Promise.all() function takes array of promises. It waits for all promises in the iterable to resolve or rejects as soon as one promise is rejected. So, if all the promises are resolved, it will return the array of results. If one of the promise rejects, then it will return the error.

const promise1 = Promise.resolve("A");
const promise2 = Promise.resolve("B");
const promise3 = Promise.reject("Error!");

Promise.all([promise1, promise2])
.then(console.log) // Output: ["A", "B"]

Promise.all([promise1, promise3]).catch(console.error); // Output: Error!

4. Promise.any(iterable)

Promise.any() function also takes array of promises. It waits for the first promise to resolve. If all promises reject, returns an AggregateError with the array of errors.

const promise1 = Promise.reject("Error 1");
const promise2 = Promise.resolve("Success!");
const promise3 - Promise.reject("Error 2");

Promise.any([promise1, promise2]).then(console.log); // Output: Success!
Promise.any([promise1, promise3]).then().catch(console.log);
//Output:
// [AggregateError: All promises were rejected] {
// [errors]: [ 'Error 1', 'Error 2' ]
// }

5. Promise.race(iterable)

Promise.race() function takes array of promises and returns the result of the first promise to settle (resolve or reject). So as the name suggests, it is a race and first one to settle is returned.

const slow = new Promise((resolve, reject) => setTimeout(reject, 2000, "Slow"));
const fast = new Promise((resolve) => setTimeout(resolve, 1000, "Fast"));
Promise.race([slow, fast]).then(console.log);
// Output: Fast

const fast1 = new Promise((resolve, reject) => setTimeout(reject, 1000, "Fast1"));
const slow1 = new Promise((resolve) => setTimeout(resolve, 2000, "Slow"));
Promise.race([slow, fast]).catch(console.log);
// Output: Fast1

6. Promise.allSettled(iterable)

Promise.allSettled() function takes array of promises and waits for all promises to settle, returning an array of objects with each promise’s outcome.

const promise1 = Promise.resolve("A");
const promise2 = Promise.reject("Error!");

Promise.allSettled([promise1, promise2]).then(console.log);
/*
Output:
[
{ status: "fulfilled", value: "A" },
{ status: "rejected", reason: "Error!" }
]
*/

Promise Chaining

Promises can be chained for sequential execution of asynchronous tasks. Like in the callbacks, you will not have to go through error handling in each callback function and we will avoid the callback hell in the process.

const fetchData = () => Promise.resolve("Data");
const processData = (data) => Promise.resolve(data + " processed");
const saveData = (data) => Promise.resolve(data + " saved");

fetchData()
.then(processData)
.then(saveData)
.then(console.log) // Output: Data processed saved
.catch(console.error);

I hope this article helps you to understand and the usages of promise better. Please drop a comment if you have any questions or clarifications. Thank you for reading.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Prajwal Bati
Prajwal Bati

Written by Prajwal Bati

Full Stack | MERN | MEAN | Blockchain | Javascript

No responses yet

Write a response