Exciting Async function combine with await expression to replace promises in ES6: part 1

Just like other ES6 features async function and await expression made a huge difference inside Javascript language. Combining these two we can better control promises and replace them when needed.

Async function declaration

Technically async function defines an asynchronous function that has an implicit Promise to return its result. We simply add async to the beginning of the function.

Async function syntax with await expression

Generally we know that everything in Javascript executes synchronously. Therefor to make asynchronous calls we need to change the code structure so that we get the results we desire. As a comparison to promises this is how it looks like:

// Async/Await version
async function helloAsync() {
  return "hello";
}
// Promises version
function helloAsync() {
  return new Promise(function (resolve) {
    resolve("hello");
  });
}

Await expression

In addition await expression which only works inside an async function (otherwise throws an Error) pauses the async function’s execution and returns whatever the function returns when it is done. Therefor the function’s promise is being resolved in another word.

Async await simple example

Normally we write code which looks like this using promises and then method:

const makeRequest = () =>
  getJSON()
    .then(data => {
      console.log(data)
      return "done"
    })
makeRequest()

We know that getJSON returns a promise and then we use that data and return “done”. We could write it this way using async await:

const makeRequest = async () => {
  console.log(await getJSON())
  return "done"
}
makeRequest()

Any async function returns a promise implicitly, and the resolve value of the promise will be whatever you return from the function (which is the string "done" in this case).

Therefor we have await for getJSON which means it console.log waits until getJSON resolves its promise and returns its value.

Error handling in async function

Obviously we have to use error handling to make sure we will catch unwanted results and errors. One of the best ways is to put the code in the old try and catch block:

const makeRequest = async () => {
  try {
    // this parse may fail
    const data = JSON.parse(await getJSON())
    console.log(data)
  } catch (err) {
    console.log(err)
  }
}

We see how clean and neat the code looks like. Also it is more maintainable and easy to understand.

Using async function in a forEach loop

A promise chain with Async function and await

Sometimes working with API’s we might have chain of promises. Imagine this code:

function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch(e => {
      return downloadFallbackData(url)  // returns a promise
    })
    .then(v => {
      return processDataInWorker(v); // returns a promise
    });
}

The returned data has been split into a few parts. Using Async function and its await expression we could change the code to below:

async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url); 
  } catch(e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

Basically we are using try catch block to make it easier to manage. The important note here is the return value of async function does not have await on it because it implicitly wrapped in Promise.Resolve.

In the next article I will demonstrate this subject with more advanced examples.

Thank you for reading.

© 2019
Azadeh Faramarzi

This site is created and maintined by Azadeh Faramarzi , A passionate developer, sport and code lover who loves to share and write when she have some time.