Javascript: Understanding Promises in depth

An important part of understanding how Promises work is to understand how they can be created and the way to handle promise objects when we encounter them. In this article, we will look at both aspects of the Promise API.

Author Image
Omar Mohammad4 min read

Before we do so, let’s do a quick recap, here’s what we know,

  1. Javascript can be both Async or Sync based on the need.
  2. The promise API is a way to make JS work Async without the hassles that come with using callback functions.
  3. A promise is a Javascript object that holds the eventual result of an Asynchronous operation.
  4. A promise basically promises that you that it will give you the result of an Async Operation.
  5. It can either result in a value or error.

Status of a Promise

Before we dig in deeper let’s make sure we are clear on what the Promise Status of a Promise object really vindicates.

This promise object can be in one of three states:

1. Pending

When we create a promise object it is in a pending state.

2. Resolved (or Fulfilled)

If we get what we want from the promise it gets resolved.

3. Rejected

If we don’t get what we want from the promise it gets rejected.

Creating a Promise in JS

To create a Promise Object in JS we use the Promise Constructor. The Promise Constructor takes an Immediately invoked function expression as an argument. That function has two arguments: reject and resolve. We will look upon these in a moment.

Let’s say we want to create a promise Object that resolves to 100.

In your code editor/browser console type the following:

const p = new Promise(function(resolve, reject) {

  console.log(‘Created Promise!’);

  setTimeout(() => {

    resolve(100);

  }, 3000);

})

What is happening here?

Here, ` Promise` is nothing but a constructor provided by Javascript that lets us create and set up a promise object using the ‘new’ keyword.

As stated above, the constructor accepts a function that is immediately called into action. This might seem similar to using a callback function, but the promise constructor exposes something that is more powerful and flexible.

Now, this function requires resolve and reject argument to be supplied to it which again are also a function that does what their names say. At an elementary level, when we say resolve(100), we tell JavaScript: “Do this Asynchronously and if you manage to do it, give me back a 100”.

So if you do

console.log(p)

The result is:

You have now successfully created your first promise!

Handling Promises

Often, the result of resolve or reject needs additional work. This is because the promise object as we learned before is composed of both the status of the promise as well as its value. Luckily the Promise API also exposes some powerful methods that can be attached to a promise.

Continuing from the example code above, let us add another line of code underneath the console.log(p)

p.then(() => console.log(p))

You should see the following in your browser console:

So what’s happening here?

We are using the .then(), a method provided by the promise API to print out the promise object once it has successfully resolved.

The then() method also returns a promise and takes two arguments. Callback functions for success and failure.

Some important points to remember about the .then() is best summarized by quoting what is written on MDN docs:

If a handler function:

  • returns a value, the promise returned by then gets resolved with the returned value as its value.
  • doesn’t return anything, the promise returned by then gets resolved with an undefined value.
  • throws an error, the promise returned by then gets rejected with the thrown error as its value.
  • returns an already fulfilled promise, the promise returned by then gets fulfilled with that promise’s value as its value.
  • returns an already rejected promise, the promise returned by then gets rejected with that promise’s value as its value.
  • returns another pending promise object, the resolution/rejection of the promise returned by then will be subsequent to the resolution/rejection of the promise returned by the handler. Also, the value of the promise returned by then will be the same as the value of the promise returned by the handler.

Go ahead and give the promise API a spin!

We will look at error handling using catch() next week! Stay tuned!