DEV Community

Cover image for Async, await and generators
Prince Thomas
Prince Thomas

Posted on

Async, await and generators

You may have heard that async and await is a syntactic sugar for promises. Promise works perfectly for asynchronous tasks such as I/O operations, API calls etc... So why do we need async and await

Issues with Promise

Readability

Consider the following snippet

const sleep = (delay) =>
  new Promise((resolve) => setTimeout(() => resolve(`sleep ${delay}`), delay));
const result = sleep(1000)
console.log(result);
Enter fullscreen mode Exit fullscreen mode

sleep -> promise that resolves after given delay
When you try to run the code, the expected output is

sleep 1000
Enter fullscreen mode Exit fullscreen mode

Instead

Promise { <pending> }
Enter fullscreen mode Exit fullscreen mode

To get the expected result you have to do the following change

sleep(1000).then(console.log)
Enter fullscreen mode Exit fullscreen mode

The issue with this is, the task that needs to be executed after fulfilling the promise needs to written in the then block. This means whatever written after promise will be executed before the then block. This may cause confusion because the execution of the code is not linear.

Error handling

Promise gives pretty good API to handle the error situations. Errors can be handled in the catch block just like then block. The traditional try, catch will not work in case of promise since execution of promise is after executing the try and catch

Async and await

Async and await introduced to JavaScript in ECMA 2017, which helps to resolve the above issues. The code become linear and try catch can be used to handle the errors

const sleep = (delay) =>
  new Promise((resolve) => setTimeout(() => resolve(`sleep ${delay}`), delay));

async function asyncFunc() {
  try {
    const result = await sleep(1000);
    console.log(result)
  } catch (e) {
    console.log(e);
  }
}

asyncFunc()
Enter fullscreen mode Exit fullscreen mode

When you are using await, it will wait for the promise to either resolve or reject, then only the next line executes. The above snippet looks simple JavaScript except two weird keywords :D

await only can be used inside an async function

Implementation of async await with generator

Few things to consider

  • await is added before a promise
  • Next line is executed after completing the promise
const sleep = (delay) =>
  new Promise((resolve) => setTimeout(() => resolve(`sleep ${delay}`), delay));

function awaitFunc(promise) {
  promise.then((res) => iterator.next(res));
}

function* asyncFunc() {
  try {
    const result1 = yield awaitFunc(sleep(1000));
    console.log(result1);
    const result2 = yield awaitFunc(sleep(2000));
    console.log(result2);
  } catch (error) {
    console.log(error);
  }
}

var iterator = asyncFunc();
iterator.next();
Enter fullscreen mode Exit fullscreen mode

The above snippet give exact result as async and await
In here consider

  • awaitFunc accepts a promise and resolve and let generator continue the execution
  • function* to be async
  • yeild and awaitFunc to be await

Top comments (0)