DEV Community

Anand Kumar
Anand Kumar

Posted on • Updated on • Originally published at elanandkumar.com

ES6 and Beyond > Part 2

This post is second part of the previous one. If you haven't read it yet, read it here:

In this article, we are going to learn about promises and the new & improved/alternate way to achieve asynchronous task using async/await instead of promise.

The objectives are to learn following:

  • Promise
  • Promise.prototype.finally
  • async/await
  • for...await...of

Promise: An Introduction

So, what is promise?

It is an object, which guarantees us to return a single value some time in future for an asynchronous operation.

Let's understand it a bit more by understanding the states that a promise can have. A promise is an object (mentioned above) can have 3 states:

  • fulfilled: When promise is resolved/fulfilled.
  • rejected: When a promise failed to get fulfilled.
  • pending: Neither rejected not fulfilled is the pending state.

Now here is the syntax on how to write a promise in javascript:

An explanation on above code.

  • Line 2: We are creating/constructing a promise object. state would be pending and result will undefined
  • Line 7: Promise is getting resolved here so the state would be fulfilled with a returned value of the string inside resolve.
  • Line 10: Promise is getting rejected here. The state would be rejected and sets the result to error with the error value provided.

Now, we can use the promise object as shown below:

promise.then(
  success => console.log(success),
  error => console.log(error)
);

So, promise provides then-ability which is what guarantees us to get the data once a promise is resolved/rejected.

Finally, we can derive some rules regards to Promise:

  • A promise provides then() method.
  • A pending promise can result to either 'fulfilled' or 'rejected' state
  • A fulfilled or rejected promise is considered as settled. So, it must not transition to any other state.
  • Once a promise is settled, it should have a value which must not change.

A bit more on then is needed. Right? Ok, let's first look at the syntax of then:

promise.then(onFulfilled[, onRejected]);
  • onFulfilled: Callback for resolved/fulfilled promise
  • onRejected (optional): Callback for rejected promise

One of the great thing about promise is chaining

To achieve the chaining, we use then() method provided by promise. Let's have a look at following example.

const promise1 = promiseOne()
const promise2 = promise1.then(onFulfilled, onRejected)
// OR
const promise = promiseOne().then(onFulfilled, onRejected)

So, each promise represents the completion of another asynchronous step in the chain.

Before promise arrived, we fall in a classic callback pyramid of doom trap. Let's have a look:

But, with promise, we use the callback on returned promise instead to form the promise chain which makes code better and more readable.

catch looks new here, right? Ok. so catch is another method provided by promise which catches any kind of error that might have happened while promise tries to fulfil.

It is completely possible to chain after catch using then.

Promise.prototype.finally

This is again part of promise Promise.prototype.finally. It is useful when we wants to execute some sort of code regardless the outcome of the promise (be it fulfilled or rejected). Syntax is given below.

Let's move to our next point which is async/await

async/await

async/await is nothing more than syntactic sugar for promises that we learnt above. Let's look at the syntax first:

Let's say we need to fetch json file from a url. Here is how we will write it using promise.

const getJson = url => fetch(url).then(json => console.log(json))
// call the getJson method
getJson('https://jsonplaceholder.typicode.com/todos/1')

Now, let's have a look on how we can use async/await for this.

Both implementation are doing the same thing but async/await is more readable. As I have mentioned before about chaining, promise/then makes code less readable when we start doing the chaining but with async/await, you get more neat and clean code. Example given below to explain it. Here, I have created three promises:

Now have a look at the usage of promise and async/await

The promise way

The async/await way:

So, which one you prefer. Let me know in the comment section. Personally, I like async/await. It makes code more readable in synchronous way which leads to more manageable code.

Tip:

await can only be used inside async function.

Go ahead and do practice this at your own. Have questions, feel free to drop a comment with your question.

for...await...of

This one is related to await that we learnt just now. This helps us to iterate over async iterable objects as well as on sync iterables which includes built in string, array or array like objects (eg. arguments). Syntax:

for await (let item of iterable) {
    // code goes here...
}

Let's take an example. Suppose, we need to fetch data from 3 urls. The urls are stored in an array.

I am sure you also realise how clean it is and how useful it can be. So, practice, practice and practice.

Summary

Today we learnt about Promise. The newer and nicer way to use the Promise by using async/await. We also looked at finally along with how to iterate on await using for...await...of. Some of the terminology to remember are:

  • Promise
  • resolve/fulfilled
  • reject
  • settled
  • chaining
  • then
  • catch
  • finally
  • async
  • await
  • for...await...of

There are chances that you have questions around some of the points above which is not explained. It is kind of done intentionally so that you can come up with questions and also start exploring at your own. For any questions, drop a comment and own awesome community folks or myself will help you to get it answered.

Here are two questions from me for you to answer.

Q1: How to use multiple promises in parallel?

Q2: How can we solve Q1 with async/await

Thanks for reading. Happy learning.

--
Originally published at https://elanandkumar.com/blog/es6-and-beyond-II

Top comments (0)