DEV Community

Faithful Ojebiyi
Faithful Ojebiyi

Posted on • Updated on

An Ultimate Guide to Javascript Promises.(code Examples)

Alt Text

In this tutorial we would be talking about all the JavaScript promises, their differences and their use cases.

Introduction

Promises are a way to implement async programming in JavaScript(ES6). A Promise will become a container for future value. In a layman's term, you place and order for an item on Amazon. After your order is placed you receive a receipt with delivery date in your mailbox . The receipt in this case stands as a promise that your order will be delivered to you. The receipt is like the container or a proof of the item you order(future value).

For asynchronous programming, JavaScript used callbacks but there is a problem with using callbacks which is callback hell.

Callback might seem ok for little applications but when it comes to complex application with a lot of callbacks, you begin to have a lot of deeply nested callback functions which might become very difficult to read, understand or mange.

An example of callback hell

func1(function(a){ 
 func2(a, function(b){ 
  func3(b, function(c){ 
   ... 
  }); 
 }); 
});
Enter fullscreen mode Exit fullscreen mode

Promises to the Rescue

A Promise is basically created when we are unsure of whether or not the assigned task will be completed. The Promise object represents the eventual completion (or failure) of an async(asynchronous) operation and its resulting value. As the name suggests, a Promise is either kept or broken.
A Promise is always in one of the following states:

  • fulfilled: Action related to the promise succeeded.
  • rejected: Action related to the promise failed.
  • pending: Promise is still pending i.e not fulfilled or rejected yet.
  • settled: Promise has fulfilled or rejected

Syntax

const promise = new Promise((resolve,reject) => {....});
Enter fullscreen mode Exit fullscreen mode

Example

const myPromise = new Promise((resolve, reject) => { 
 if (Math.random() > 0) { 
  resolve('Hello, I am positive number!'); 
 } 
 reject(new Error('I failed some times')); 
})
Enter fullscreen mode Exit fullscreen mode

I published an article about "the new features in ECMAscript 2021" Where I talked about promise.any() 1 and people asked about the differences between Javascript promises. So here am I with another article to clear any confusion you might have about the various implementations of Javascript promises.

Promise.All()

The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will resolve when all of the input's promises have resolved, or if the input iterable contains no promises. If any of the promises is rejected promise.all() throws and error with the first rejected promise

Let's take this example below. We create 3 promises to resolve at random times.

const prom1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("first promise resolved")
    // reject("first promise rejected")
    }, Math.floor(Math.random() * 100)
  );
});
const prom2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("second promise resolved")
    // reject("second promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});
const prom3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("third promise resolved")
    // reject("third promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});

(async function() {
  try {
    const result = await Promise.all([prom1, prom2, prom3]);
    console.log(result);
  } catch (err) {
    console.log(err)
  }

})();
Enter fullscreen mode Exit fullscreen mode

If we take a look at our result in console, we can see that all three promises resolves.
Alt Text

Now, what if one of our promises is rejected? We have handled that error easily inside our try catch block.

const prom1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("first promise resolved")
    // reject("first promise rejected")
    }, Math.floor(Math.random() * 100)
  );
});
const prom2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve("second promise resolved")
    reject("second promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});
const prom3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("third promise resolved")
    // reject("third promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});

(async function() {
  try {
    const result = await Promise.all([prom1, prom2, prom3]);
    console.log(result);
  } catch (err) {
    console.log(err)
  }

})();
Enter fullscreen mode Exit fullscreen mode

Taking a look at console, we can see the rejected promise logged in console.
Alt Text

Promise.race()

The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.

Example

const prom1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("first promise resolved")
    // reject("first promise rejected")
    }, Math.floor(Math.random() * 100)
  );
});
const prom2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("second promise resolved")
    // reject("second promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});
const prom3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("third promise resolved")
    // reject("third promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});

(async function() {
  try {
    const result = await Promise.race([prom1, prom2, prom3]);
    console.log(result);
  } catch (err) {
    console.log(err)
  }

})();
Enter fullscreen mode Exit fullscreen mode

if we check our console only, one promise is returned and that's the promise that settles first either its resolved or rejected.
Alt Text

Promise.any()

Promise.any() is like the opposite of Promise.all(). Promise.any() resolves if any of the supplied promised is resolved unlike promise.all() which waits for all promises to resolve before it resolves.
lets take a look at the example below.
Basically, we have 3 promises that resolves at random times. We have used setTimeout() function to set a time taken for each promise to resolve. We used Math.floor(Math.random) to give a random time to the setTimeout function so we really dont know which promise resolves first. This is exaclty what happens in real life secenario.

const prom1 = new Promise((resolve, reject) => {
  setTimeout(
    () => resolve("this is the first promise"),
    Math.floor(Math.random() * 100)
  );
});
const prom2 = new Promise((resolve, reject) => {
  setTimeout(
    () => resolve("this is the second promise"),
    Math.floor(Math.random() * 100)
  );
});
const prom3 = new Promise((resolve, reject) => {
  setTimeout(
    () => resolve("this is the third promise"),
    Math.floor(Math.random() * 100)
  );
});

(async function() {
  const result = await Promise.any([prom1, prom2, prom3]);
  console.log(result); // Prints "A", "B" or "C"
})();
Enter fullscreen mode Exit fullscreen mode

Alt Text
The good thing about promise.any() is even if one of the promises is rejected, it would continue to resolve other promise. It would only throw an aggregation error if all promises are rejected
.
Take a look at the two examples below
In the first example only on promise is rejected but it continues to resolves. In the second example all there promises are rejected hence we get an aggregate error

const prom1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve("first promise resolved")
    reject("first promise rejected")
    }, Math.floor(Math.random() * 100)
  );
});
const prom2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("second promise resolved")
    // reject("second promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});
const prom3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve("third promise resolved")
    reject("third promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});

(async function() {
  try {
    const result = await Promise.any([prom1, prom2, prom3]);
    console.log(result);
  } catch (err) {
    console.log(err, 'all promises rejected')
  }

})();
Enter fullscreen mode Exit fullscreen mode

Alt Text
Example 2

const prom1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve("first promise resolved")
    reject("first promise rejected")
    }, Math.floor(Math.random() * 100)
  );
});
const prom2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve("second promise resolved")
    reject("second promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});
const prom3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve("third promise resolved")
    reject("third promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});

(async function() {
  try {
    const result = await Promise.any([prom1, prom2, prom3]);
    console.log(result);
  } catch (err) {
    console.log(err, 'all promises rejected')
  }

})();

Enter fullscreen mode Exit fullscreen mode

Alt Text

promise.allSettled()

The Promise.allSettled() method returns a promise that resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.
In the example below one of the promises is rejected but promise.allSettled() still returns all settled promises.

const prom1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("first promise resolved")
    // reject("first promise rejected")
    }, Math.floor(Math.random() * 100)
  );
});
const prom2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("second promise resolved")
    // reject("second promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});
const prom3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve("third promise resolved")
    reject("third promise rejected")
  }, Math.floor(Math.random() * 100)
  );
});

(async function() {
  try {
    const result = await Promise.allSettled([prom1, prom2, prom3]);
    console.log(result);
  } catch (err) {
    console.log(err)
  }

})();
Enter fullscreen mode Exit fullscreen mode

Alt Text

Conclusion

In this tutorial, we have been able to point out the difference between JavaScript Promises and what they do.
If you have any additions or reservations, let me know in the comment below.

Discussion (0)