DEV Community

Cover image for ๐Ÿš€ Demystifying Async/Await as Generators + Promises
Sagar Rout
Sagar Rout

Posted on • Edited on

๐Ÿš€ Demystifying Async/Await as Generators + Promises

  • Async/Await solves the problem of Inversion of Control with callbacks.
  • Generators build-up to Async/Await


Introduction

JavaScript being single-threaded, should not be blocked for long-running tasks.
Callbacks are the answer to execute such tasks without blocking the main thread. However, they cause Inversion of Control. The invocation of callbacks is passed to a function over which you do not have control.

Async/Await solves that problem. In this article, we would compare the same example and break down the similar working of the async/await function with the help of generators.


Async/Await

Async functions help us write asynchronous code (Promises) in a more synchronous manner.

Things to note about async functions -

  1. Async functions always return a Promise, returned values are enclosed in a promise if they are not thenables.
  2. Await keyword can only be used within an async function, it is used to await the value of a promise.

async await example

In the above snippet, the invocation of the async function returns us the data, without having to do a .then over the two promises returned from the fetch API and its parsing process.


Generators

Generators are functions that do not run to completion. They can be paused and resumed. Until the function is completed, its context is preserved. It returns a generator object which has the information about the function context. It can be inspected by logging an execution of a simple generator function. This helps us write asynchronous code in a somewhat synchronous manner.

generator example

  1. The generator object is compatible with the Iterable protocol, thus a .next() can be invoked to get subsequent values i.e. control goes back within the generator function.
  2. Values are exchanged between the generator function and outer code via next/yield.

Iterator interface


Async/Await through generators

Understanding the generators is essential for the last part of the article. It is where Promises and Generators will be composed to create our own async/await implementation.

almost there

The above code snippet is analogous to the async/await code snippet at the top. Here is the breakdown of the steps -

  1. A generator function is required for it, yield is analogous to the await keyword.
  2. The asyncify function returns a Promise, which embodies the await logic.
  3. The manual invocation of the iterator.next() method which was seen in the generator's example is done within the promise body.
  4. The logic would be recursively invoked until the IteratorResult has 'done' as true

asyncify

Ultimately, the asyncified function would be consumed in a similar manner as an async function is. As it returns a Promise, it should be consumed via a success and error handler.

asyncified consumption


All above snippets can be run here
Reference: ExploringJS

That's all people!

Top comments (1)

Collapse
 
vikas_goyal_21c510a14e21b profile image
VIKAS GOYAL

Great article! Really love the clear and concise illustrations!