- Async/Await solves the problem of Inversion of Control with callbacks.
- Generators build-up to Async/Await
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 functions help us write asynchronous code (Promises) in a more synchronous manner.
Things to note about async functions -
- Async functions always return a Promise, returned values are enclosed in a promise if they are not thenables.
- Await keyword can only be used within an async function, it is used to await the value of a promise.
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 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.
- 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.
- Values are exchanged between the generator function and outer code via next/yield.
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.
The above code snippet is analogous to the async/await code snippet at the top. Here is the breakdown of the steps -
- A generator function is required for it, yield is analogous to the await keyword.
- The asyncify function returns a Promise, which embodies the await logic.
- The manual invocation of the iterator.next() method which was seen in the generator's example is done within the promise body.
- The logic would be recursively invoked until the IteratorResult has 'done' as true
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.
That's all people!