In this article I will describe how the ES2017 `async` functions are essentially a play between two older [JavaScript](https://hackernoon.com/tagged/javascript) features: `generators` and `promises`, both of which were added earlier to the language in the ES2016 specification. #### Before you start reading .. * This article is **not** an introduction to `promises`, `generators` or `async` functions. * The **only** goal of this article is to describe how `async` functions can be realised using `promises` and `generators`. * It does **not** offer any opinion whether `async` functions are better or worse than the other approach. * The code examples used in this article are ingeniously contrived for easier explanation. They are **not** meant for any serious use. #### But why .. ? Since `async` functions are now natively supported, what is the need to understand how they work? Well, apart from the obvious reason of **_curiosity_**, an important reason is supporting older platforms. If you want your code using these newer features to run on older browser versions or older Node.js versions, you would be required to use [tools](https://hackernoon.com/tagged/tools) like [Babel](https://babeljs.io/) to transform these newer features into older features. Therefore, a solid understanding of how `async` functions get decomposed into `generators` and `promises` can come in handy when reading/debugging your transformed code. For example, here is a simple example of an `async` function : This function gets transformed by Babel into the following ES2016 code (don’t worry about understanding it right now, we will cover it later) :  Babel output for the previous async function (ES2016) They look really different! However, if you understand how `async` functions actually work, then this transformation is fairly obvious. Another fun fact, browsers also implement `async` functions in a similar fashion i.e. they [transform](https://www.reddit.com/r/javascript/comments/44b6y9/question_how_are_generators_and_asyncawait/czp1lxr/) the `async` code to use `generators` and `promises` quite similar to Babel. ### Okay, so how does it happen ? Sometimes in order to understand how something works, the best way is to build it yourself. So let’s flip the question: > Imagine we are given a piece of code that uses `async` functions, how can we rewrite it using only `promises` and `generator` functions? Here’s an `async` function :  It performs three asynchronous tasks, one after the other where each task depends on the completion of the previous task. Finally, it returns the result of the last task. #### How can we write it using generators ? [Generators are functions which can be exited and later re-entered.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function%2A) Let’s quickly recap how they work. Here’s a simple generator function :  This generator-function `gen` has some interesting aspects (lifted from the [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) docs) : 1. When a generator function is called, its body is not executed right away. Instead it returns an iterator-object which adheres to the [iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol) i.e. it has a `next` method. 2. The only way to execute the body of `gen` is by calling the `next` method on its iterator-object. Every time the `next` method is called, its body is executed until the next `[yield](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield)` expression. The value of this expression is returned from the iterator. 3. This `next` method also accepts an argument. Calling it with an argument replaces the current `yield` expression with the argument and resumes the execution till the next `yield` expression. #### To elucidate (very, very crudely) .. * A generator-function gets executed `yield-by-yield` (i.e. one yield-expression at a time), by its iterator (the `next` method). * Every `yield` has a _give_ → _halt_ → _take_ behaviour, so to say. * It _gives_ out the value of the current yield-expression, to the iterator. * It then _halts_ at this point, until the iterator’s `next` method is called again. * When the `next` method is called again, it _takes_ the argument from it and replaces the currently halted yield-expression with it. It then moves to the next `yield`. _You may want to read the above summary again or refer to the_ [_amazing MDN docs_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*)_!_ #### But how does this help us ? By now you would be wondering, how do the generator functions help our situation? We need to model an asynchronous flow where we have to wait for certain tasks to finish before proceeding ahead. But so far in our discussion everything has been synchronous. How can we do that? > Well, the most important insight here is that the generator-functions can yield `promises` too. A `generator` function can `yield` a `promise` (for example an async task), and its iterator can be controlled to _halt_ for this `promise` to resolve (or reject), and then proceed with the resolved (or rejected) value. This pattern of weaving a an iterator with yielded `promises` allows us to model our requirement like this :  _(Notice how this generator function resembles our_ `_async_` _function!)_ But this is only half the story. Now we need a way to execute its body. We need a function that can control the iterator of this `generator` function to _halt_ every time a `promise` is yielded and proceeds once it resolves (or rejects). It sounds complicated, but is very simple to implement, as shown below :  A function that executes a generator function. (Only for explanation, **do not use it !**) Now we can execute our `generator` function `init` using this `runner` function as shown below:  Use \`runner\` to execute the body of \`init\`. And that’s it! This combination of a `runner` function and our `generator` function achieves a similar outcome as the original `async` function. _Please note that this_ `runner` _function is only for demonstrating the concept. It is_ **_not_** _suitable for any serious use. If you are looking for a proper implementation, you can find it_ [_here_](https://gist.github.com/jakearchibald/31b89cba627924972ad6)_._ ### To summarise We started with an `async` function and then we wrote an identical implementation using `generators` and `promises`. That is, the following two pieces of code will have a similar effect :  #### Further exercises * In the beginning of this article, we looked at how Babel transforms `async` code to ES2016 code using `generators` and `promises`. You can now revisit that transformed code and compare how our `runner` function is similar to the `_asyncToGenerator` function. In fact, that `_asyncToGenerator` function is the foolproof version of our extremely simple `runner` function. * If you are still interested, you can go another step forward i.e. transform `async` functions to ES2015 code i.e. without `generators`. For this you would have to emulate `generators` themselves (using a stateful busy loop with `switch` cases for e.g. see the [regenerator project](http://facebook.github.io/regenerator/)). I hope this explanation clears up the mystery behind `async` functions. They offer a simpler syntax and therefore less code noise. The proposal for `async` functions states that : > [The introduction of Promises and Generators in ECMAScript presents an opportunity to dramatically improve the language-level model for writing asynchronous code in ECMAScript.](https://github.com/tc39/ecmascript-asyncawait#async-functions-for--ecmascript) Thanks to [Akos](https://github.com/kittaakos), [Alisa](https://github.com/alisa-lisovskaya) & [Kristian](https://twitter.com/kristianduske) for providing their feedback to improve this article.