Renato Pozzi's Blog

Renato Pozzi's Blog

Explain Me Like I'm 5: What are Javascript Promises?

Explain Me Like I'm 5: What are Javascript Promises?

Subscribe to my newsletter and never miss my upcoming articles

New to Javascript?

Maybe are you looking for a clean and absolutely not annoying guide about promises?

Welcome to paradise!

What are Promises?

Ok so you want a new iPhone, the new iPhone 13 right, yeah it's you know, something cool.

To get your iPhone you make a pre-order to Apple, saying "Ok, take my money and when your iPhone is ready send it to my home", and Apple answers: "Ok bro!".

After a while, your intercom rings, it's the delivery boy delivering your new iPhone! So now, you can take pictures of your cat, or dropping it from 30 meters in order to test the ceramic shield, and so on...

Ok... So what the fu*k has this stuff got to do with it?

Fun fact: I have an iPhone. But understanding this makes you understand how a promise works in Javascript!

First of all, a promise is a special javascript object that connects a function (in our case, your pre-order) that can last indefinitely. With another function that can access at the value (in our case, the iPhone) provided by the function when it finishes!

So, you can have your iPhone at home only when it's available for delivery. If not, you need to (a)wait for availability.

Ok ok, I know is quite confusing, but let's do some real examples:

How do I declare a Promise?

This is the simplest method to declare a Promise:

const promise = new Promise((resolve, reject) => {});

The promise constructor takes one argument, a callback with two parameters, resolve and reject. Do something within the callback, perhaps async, then call resolve if everything worked, otherwise call reject.

This example reflects the little story of the introduction:

const iPhoneIsAvailable = async () => ({ uuid: '000DXXIOFF-SD32F-SD3F-DS23' });

const buyNewPhone = new Promise(async (resolve, reject) => {
  try {
    const iPhone = await iPhoneIsAvailable();
    resolve(iPhone);
  } catch (err) {
    reject(err); 
  }
});

buyNewPhone.then(res => console.log('Res:', res));

As you can see, we are creating a promise, and also, we subscribe to the returned value using then in the last row.

But, why do we have to do then to our promises?

Well, you should know that promises have 4 statuses:

  • Fulfilled - The action relating to the promise succeeded
  • Rejected - The action relating to the promise failed
  • Pending - Hasn't been fulfilled or rejected yet
  • Settled - Has fulfilled or rejected

The first state, just after the declaration is the pending state, this value will be the same until the promise callback calls a resolve or a reject.

The other states are self-explanatory, when the promise is settled (no matter what is the result), you can have fulfilled (if the promise goes ok and our iPhone has been delivered!) but also you can have rejected (if the promise goes ko and our iPhone is not available)

In our case, we can check for every state using these methods:

buyNewPhone
  .then(res => console.log('Res:', res)) // Promise fulfilled
  .catch(err => console.log(err)) // Promise rejected
  .finally(() => console.log('Finished')) // Promise settled, need to check if it's ok or ko.

It's important to know that then and catch are exclusive functions, either one is called, or the other is called. Finally instead, will be called all the time.

Why did you used await in your example?

Well, using the thenable functions is quite good, but there are some cases like that:

axios.get('/api/users/1')
  .then(res => {
    axios.get(`/api/users/${res.data.name}/accounts`)
      .then(res => {
        axios.get(`/api/accounts/${res.accounts[0].id}`)
          .then(res => {
            // ...ecc
          })
      })
  })

When writing promises using thenable functions is quite difficult to maintain..

In the example I'm using Axios, an HTTP Client for Javascript.

So what can we do?

Await is our solution!

Await is a special keyword used to tell javascript: "Please, this is a promise, wait for the result, before going on."

Using await you can rewrite the awful example of promise chaining this way:

const user = await axios.get('/api/users/1');
const accounts = await axios.get(`/api/users/${user.data.name}/accounts`);
const accountInfo = axios.get(`/api/accounts/${accounts.accounts[0].id}`);

This will work the same way!

Remember, you need to declare your function with the async keyword in order to use the await functionality.

So, for today is all my friend! It was a quick introduction to the world of promises, see you to the next article!

Let's Connect!: Twitter | Linkedin

 
Share this