Explaining Promises and Async/Await in Js

In this post I’m going to explain the promise and the Async/Await concepts in Javascript in a simple exercise.

So we have a regular data (Array with data) then we have a method getData that is returning us the data, so when we call that method in instants we have answer:

  // Blog
  const data = [
    {
      name: 'cristina',
      position: 'developer',
      office: 'madrid',
    },
    {
      name: 'roberto',
      position: 'manager',
      office: 'mexico',
    },
  ];

  const getData = () => {
    return data;
  };

  console.log(getData());

The result is going to appear in instants in the browser and this is because this is synchronous and our data is on our local host:

But let’s imagine that our data is not in local, maybe the data is another server or maybe we are doing an API petition that return us that data, now here is where the Asynchronous appears; so like for example every time that we do a call to an Database or we fetch data this will have an small delay it can be a millisecond but is a delay and that is the cause that we are not receiving the data immediately.

Let’s simulate that delay in our current example, and to do that we are going to use the SetTimeOut() the 2000 means 2 seconds, so the data will be consoled after 2 seconds.

  const getData = () => {
    setTimeout(() => {
      console.log(data);
    }, 2000);
  };

  getData();

After 2 seconds then we see the data:

Now if we remove the console from the SetTimeOut and we return data like this:

  const getData = () => {
    setTimeout(() => {
      return data;
    }, 2000);
  };

  console.log(getData());

This will return us undefined because is executing the the getData() directly and we are not going to receive data until 2 seconds, this is Asynchronous, so how can we fix this when we want the data and not undefined?

The Promise solve that issue and is a javascript object that handle asynchronous code, so now let’s modify our getData() using a promise so when the data is ready this will be solved or if there is any error this will be rejected after the getData() is called.

Resolve is used when we want to return the data and everything was good and if there is an error during the process we should use reject parameter.

  const getData = () => {
    return new Promise((resolve, reject) => {
      // Error validation if data is empty
      if (data.length === 0) {
        reject(new Error('Data is empty'));
      }

      // Simulate a server response & resolve promise
      setTimeout(() => {
        resolve(data);
      }, 2000);
    });
  };

How can we call the getData method?

Well we can call the method getData() adding then() this will obtain the resolved promise (the correct data) and .catch() will have the errors.

getData().then().catch();

So, the final code looks like this:

  const data = [
    {
      name: 'cristina',
      position: 'developer',
      office: 'madrid',
    },
    {
      name: 'roberto',
      position: 'manager',
      office: 'mexico',
    },
  ];

  const getData = () => {
    return new Promise((resolve, reject) => {
      // Error validation if data is empty
      if (data.length === 0) {
        reject(new Error('Data is empty'));
      }

      // Simulate a server response & resolve promise
      setTimeout(() => {
        resolve(data);
      }, 2000);
    });
  };

  getData()
    .then(response => console.log(response))
    .catch(err => console.log(err.message));

An important thing to mention is that if we just call the method inside the console like this then the status will be ‘pending‘ so we need to call the method with .then()

console.log(getData());

What about if there is an error? let set data = [] to simulate the error

  const data = [];

  const getData = () => {
    return new Promise((resolve, reject) => {
      // Error validation if data is empty
      if (data.length === 0) {
        reject(new Error('Data is empty'));
      }

      // Simulate a server response & resolve promise
      setTimeout(() => {
        resolve(data);
      }, 2000);
    });
  };

  getData()
    .then(response => console.log(response))
    .catch(err => console.log(err.message));

Result:

What about the Async/Await? well that is just a ‘sugar syntax‘ that means is designed to make things easier to read or to express. It makes the language “sweeter” for human use.

The await word replace the .then() and .catch() and also you need to call the method with the async word at the beginning because the await can only be used with async word, like this:

  const getFinalData = async () => {
    const finalData = await getData();
    console.log('finalData=>', finalData);
  };

  getFinalData();

Here the final code:

  const data = [
    {
      name: 'cristina',
      position: 'developer',
      office: 'madrid',
    },
    {
      name: 'roberto',
      position: 'manager',
      office: 'mexico',
    },
  ];

  const getData = () => {
    return new Promise((resolve, reject) => {
      // Error validation if data is empty
      if (data.length === 0) {
        reject(new Error('Data is empty'));
      }

      // Simulate a server response & resolve promise
      setTimeout(() => {
        resolve(data);
      }, 2000);
    });
  };

  const getFinalData = async () => {
    const finalData = await getData();
    console.log('finalData=>', finalData);
  };

  getFinalData();

Result is the same:

Thanks,

Cristina Rojas.