Promises are used in JavaScript to handle asynchronous operations. They essentially represent an operation that hasn’t completed yet — hence the name of ‘promise’.

They simplify the process of dealing with multiple asynchronous operations, and reduce the likelihood of “callback hell” which often leads to messy and unmanageable code.

Why use promises?

  • A better way to handle asynchronous operations
  • Improved error handling
  • And, they make for much cleaner code!

Let’s take a look at how they work..

So a promise can be thought of as a placeholder for (an unknown) value that’s expected whenever a promise is created. They allow you to associate event handlers with an asynchronous action's eventual success or failure.

This means that asynchronous methods return values in the same manner as synchronous methods — instead of immediately returning a final value, they return a promise to provide the value at some point in the future.

A promise can be in one of these states:

  • Pending: the initial state, when the operation hasn’t fulfilled or rejected
  • Fulfilled: the operation has successfully completed
  • Rejected: the operation has failed
  • Settled: the operation has either fulfilled or rejected

Let’s see how to create a promise:

let completed = true;
let promise = new Promise(function(resolve, reject) {
  // perform an action
  if (completed) {
    resolve("It worked!");
  }
  else {
    reject(Error("It didn't work.."));
  }
});

We can see that the promise constructor takes one argument, a callback with two parameters, resolve and reject. Within the callback you perform your desired action (such as an ‘async’ operation), if it’s successful, call resolve, if not call reject.

Note that in this example we reject with an Error object. It’s not mandatory, but beneficial for certain debugging tools, as they capture a stack trace.

So how do we use this promise?

promise.then(function(result) {
  console.log(result); // "It worked!"
}, function(err) {
  console.log(err); // Error: "It didn't work.."
});

We can see then()takes two arguments, a callback for “success”, and a callback for a “failure”. Both are entirely optional, you’re free to just add a callback for either success or failure if you wish.

To summarise

A promise is an object that returns a future value. It begins in the pending state and proceeds to either the fulfilled state or rejected state, before being considered settled.


Tim profile image

A little about me..

Hey, I’m Tim! 👋

I’m a freelance business owner, web developer & author. I teach both new and experienced freelancers how to build a sustainable and successful freelancing business. Check out my Complete Guide to Freelancing if you'd like to find out more.

While you're here, you can browse through my blogs where I post freelancing tips, code tutorials, design inspiration, useful tools & resources, and much more! You can also join the newsletter, or find me on X.

Thanks for reading! 🎉