TechMentorAI

Promises

in JavaScript

Published

Imagine you order something online. You pay for the item, and they 'promise' to deliver it to your location. You don't have exactly when it will come, but you are guaranteed it will arrive. JavaScript Promises are similar. They are objects that represent the eventual completion (or failure) of an asynchronous operation and its resulting value.

Imagine Promises in JavaScript

States of a Promise

A Promise in JavaScript can be in one of three states: pending, fulfilled, or rejected. 'Pending' means the Promise is still working and hasn't completed yet. 'Fulfilled' means the Promise has successfully completed. 'Rejected' means an error occurred.

Creating a Promise

In JavaScript, you can create a Promise by using the 'new' keyword and the Promise constructor. This takes one argument, a function, which in turn takes two parameters: resolve and reject. 'Resolve' is a function call when the Promise completes successfully, carrying the result. 'Reject' is called if an error occurs, carrying the error.

const promise = new Promise((resolve, reject) => {
  // Some asynchronous operation here
  if (/* everything turned out fine */) {
    resolve('Stuff worked!');
  } else {
    reject(Error('It broke'));
  }
});

Using a Promise

To use a Promise and get the result (or error), we can use '.then()' method for the success scenario, and '.catch()' for handling errors. These methods are also used for chaining Promises.

promise
  .then((result) => console.log(result))  // This will run if the Promise is successful
  .catch((error) => console.error(error));  // This will run if the Promise failed

Promise Chaining

Sometimes, operations are dependent on the result of a previous operation. If these operations are asynchronous, it can lead to 'callback hell' where callbacks are nested within callbacks making code hard to read and debug. Promise chaining is a technique to flatten the code and make it more readable and easier to understand.

// An example of Promise chaining
firstFunction()
  .then((firstResult) => secondFunction(firstResult))
  .then((secondResult) => thirdFunction(secondResult))
  .catch((error) => console.error(error));

Promise.all

Promise.all is a method that takes an array of Promises and returns a new Promise that only fulfills when all of the promises in the array have been fulfilled, or rejects as soon as one of them rejects. The result of Promise.all is an array of results from all the promises.

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => console.log(values));
// expected output: Array [3, 42, 'foo']

No Time to Read? Learn on the Go!

By reading this article, you've invested 1.50 minutes of your life into expanding your knowledge and perspectives. Now, imagine learning on-the-go, turning every moment into an opportunity for growth and discovery.

Imagine you want a new toy. You ask your parents for it, and they might say 'Okay, we promise you'll get it for your birthday'. So now, you're waiting. Your birthday isn’t here yet, so you didn't get the toy, but you have a promise that you'll get it. That’s kind of what a promise is in JavaScript. It’s a way for JavaScript to keep track of some work that it promised to do, while it’s waiting for that work to finish.

Imagine Promises in JavaScript

States of a Promise

A promise in JavaScript can be in one of three states. Imagine you are waiting for your birthday. The toy that you expect to get is like a promise. Here, the three states are:

The 'Pending' State

This is like the time when you're waiting for your birthday to come. In this state, the promise is neither fulfilled nor rejected. The toy – or promise – is on its way, but it’s not here yet.

The 'Fulfilled' State

Yay! It’s your birthday and you got the toy! Your parents fulfilled their promise. Similarly, in JavaScript when the work that was promised is finished and everything went well, the promise is 'fulfilled'. This is the best case scenario.

The 'Rejected' State

Oh no, your parents couldn’t get the toy and your birthday is here. The promise they made to you is now 'rejected'. Similarly, in JavaScript if something went wrong and the promise could not be fulfilled, it gets 'rejected'. This means the work that was promised couldn’t be completed successfully.

Handling Promises

With the toy promise your parents gave you, you were really expecting to get it on your birthday. You even made some plans - if the toy arrives, you play with it; if it doesn’t, you play with your old toys. In JavaScript, we do the exact same thing using '.then' for the case when we get our toy or the promise is fulfilled, and '.catch' for the case when we don't get our toy or the promise is rejected. This is called 'Handling Promises'.

let toyPromise = new Promise(function(resolved, rejected) { /* some code */ });
toyPromise.then(function(toy) { /* code to play with toy */ })
.catch(function(reason) { /* code to play with old toys */ });

Chaining Promises

Let’s say your parents promised you two toys now, one for your birthday and another for Christmas. Christmas is after your birthday, so the second promise depends on the first one. In JavaScript, we call this dependency as 'Chaining Promises'. After getting the first toy, you can start another promise for the Christmas toy! You can chain them together so you can handle them in order.

toyPromise.then(function(birthdayToy) { /* play with birthday toy */
return new Promise(function(resolved, rejected) { /* Christmas toy promise */ });})
.then(function(christmasToy) { /* play with Christmas toy */ })
.catch(function(reason) { /* handle any broken promises */ });

Async/Await

When you are waiting for your first promised toy, you can’t accept the second toy. You have to wait until it’s your birthday, get your birthday toy, then wait until Christmas to get your Christmas toy. In JavaScript, we can represent this waiting using keywords 'async' and 'await'. If your function needs to wait for a promise to complete, you add 'async' before the function and 'await' before the promise. This tells JavaScript to wait for the promise to finish before moving on to the next line of code.

async function waitAndPlayWithToys() {
let birthdayToy = await toyPromise;
/* play with birthday toy */
let christmasToy = await christmasPromise;
/* play with christmas toy */
}

No Time to Read? Learn on the Go!

By reading this article, you've invested 2.53 minutes of your life into expanding your knowledge and perspectives. Now, imagine learning on-the-go, turning every moment into an opportunity for growth and discovery.

To understand how Promises are used in real JavaScript coding, see Asynchronous JavaScript

About author

Roman Y.
Senior Software Engineer at Nike

Why did I decide to launch this website? Drawing from my rich background in interviewing candidates for a variety of developer roles, I've observed a common pattern: many applicants share similar deficiencies in their knowledge during technical interviews. Motivated by this insight, I established this website with the aim of assisting developers in securing their ideal job. Through straightforward and concise articles, my goal is to not only deepen your understanding of programming language nuances but also to equip you with the insights needed to deliver the precise answers interviewers expect. Essentially, you'll be providing the correct response. I encourage you to spread the word about this site on social media platforms. Echoing the wisdom of an Armenian saying: "Do good and cast it into the water."

EXCLUSIVELY

Certain articles only distributed to subscribers through email