An Async function returns a promise immediately, so whats the difference between this and a normal promise? the main one is that you can use something call await, this await call will pause the promise until is resolved, after that it will return the resloved value, if not, it will reject the promise.

Basic example

  const messageAfter2Seconds = new Promise(( resolve,reject ) => {
    setTimeout(() =>{
      if (true){
        resolve('You can say hello');
      } else { 
        reject('Rejected');
      }
    }, 2000);
  });

  async function add(x) {
    const a = messageAfter2Seconds;
    return `${await a} ${x} `;
  }

  add('to this bad boy!').then(y => {
    console.log(y);  // You can say hello to this bad boy! after 2 seconds.
  });

Going deeper with the previous example

    function messageAfter2Seconds(x) {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve('You can say hello');
        }, 2000);
      });
    }

    async function addBoy(x) {
      const a = await messageAfter2Seconds();
      return `${a} ${x}`;
    }

    addBoy('to this bad boy').then(y => {
      console.log(y);  // You can say hello to this bad boy after 2 seconds.
    });

    async function addAnotherBoy(x) {
      const a = await messageAfter2Seconds();
      await messageAfter2Seconds(); // Here we pause the call for 2 secs
      return `${a} ${x}`;
    }

    addAnotherBoy('to this other bad boy').then(y => {
      console.log(y);  // You can say hello to this other bad boy after 4 seconds.
    });
  

Notice how on the addAnotherBoy function we have to run the await messageAfter2Seconds() alone so the second message can be print after the first one ( 2 seconds ), the code allow us to read syncronus even though everything is happening asynchronous, is more clear and readable.

Let's do an api call

I'll use the popular library axios to make things a bit easier

    import axios from 'axios';
    
    async function data(user) {
      axios.get(`https://api.github.com/users/${user}`)
      .then(response => {
        const { name, id } = response.data;
        console.log(name);
        console.log(id);
      }).catch(error => {
        console.log(error)
      });
    };

    data('Rolando-Barbella'); 
    // Rolando Barbella
    // 6339809
  

With async await things look clearer and easier

    import axios from 'axios';

    async function data(user) {
      const response = await axios.get(`https://api.github.com/users/${user}`);
      const { name, id } = response.data;
      console.log(name);
      console.log(id);
    };

    data('Rolando-Barbella'); 
    // Rolando Barbella
    // 6339809
  

Handeling errors

We off course need to take care of errors in case something goes wrong, with async function we can use try and catch staments which by the way is something that is not possible to use with plain promises because they are allways invoque asynchronous

    import axios from 'axios';

    async function data(user) {
      const response = await axios.get(`https://api.github.com/users/${user}`);
      const { name, id } = response.data;
      return response.data;
    }
    
    async function showUser(user) {
      try {
          const user = await data(user);
          console.log(user.name);
          console.log(user.id);
      } catch (error) {
          console.error(`Error: ${error.message}`);
      }
    }

   showUser('my-name-is-mud'); // Error: Request failed with status code 404

  

Calling multiple promises

Sometimes we need to call multiple promises, wanting them to show at the same time, but how can we do that if they take a different amount of times to resolve? We can use something call Promise.all combine with async await, which ever finish last would be the final amount of time.

    const message = (message, seconds) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if(true){
            resolve(`You can say hello to this ${message}`);
          }else{
            reject('Rejected');
          }
        }, seconds);
      });
    };

    const messageAfter2Seconds = message('bad boy', 2000);
    const messageAfter4Seconds = message('other bad boy', 4000);

    async function show(x, y) {
      const [one, two] = await Promise.all([messageAfter2Seconds, messageAfter4Seconds]);
      return {
        one,
        two,
      }
    };

    show().then(m => {
      console.log(
       `1 - ${m.one} 
        2 - ${m.two}`
      );
    }); // after 4 secs
    // 1 - You can say hello to this bad boy 
    // 2 - You can say hello to this other bad boy