Synchronous Looking Code in Asynchronous Javascript
Blogs
April 26, 2022

Synchronous Looking Code in Asynchronous Javascript

Synchronous looking code in asynchronous Javascript

Javascript allows you to write non-blocking, asynchronous code. This means if there's code that needs to wait for something else like an API response, it can make use of the event queue to let the program continue running and then return back once the response is received. This in fact makes developer’s life a lot easier not having to deal with synchronous blocking code.

If you’ve spent some time with Javascript, you should be familiar with callbacks and Promises. With the introduction of async/await, things have been a lot easier but it’s important to understand why async/await has been so important for Javascript.

Traditional ways of writing asynchronous code

Before the introduction of async/await, the most common pattern of writing asynchronous code was using callbacks. ES2015 introduced us with Promises which tried to solve some of the issues of callback functions like “Inversion of control” and “Callback hell” but at the end of the day, it was always a challenge managing complex nested level asynchronous code.

Most of the problems with callbacks and Promises are due to the way the code looks. It won’t be wrong to say that in both the cases, the code looks in a way, unnatural to our brain and how we think.

With a complex looking code, it usually brings a whole lot of other issues with it. It becomes harder to test the code, is easier to introduce bugs and can be a nightmare for someone else to maintain the code. It can obviously be cleaned up using reusable functions or multiple then chains but still you get the point that I am trying to make here. We needed a synchronous looking asynchronous code. Not just to make it look better but also to remove the other complexities that this pattern of code brought.

On comes generator functions

ES2015 introduced generator functions. Generators are basically functions that can be paused and resumed. According to this MDN document,

Generators are functions that can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances.

In the above example, calling generator(10) just returns an iterator and yield i statement is never called unless we call gen.next() which returns us the value that is being yielded. In short, the generator function doesn’t execute the entire function but waits for iterator.next() to be called and again pauses at the next yield and the cycle continues.

Now combine this with Promise and a recursive function, we have the recipe for our synchronous looking asynchronous code.

The run function takes in a generator function. We recursively iterate over the iterator calling the iterator.next function on Promise resolve until the generator has no more yield keywords before finally exiting the recursive function.

This gave developers an option to take the asynchronicity out of the equation and abstract it away and just write (and also read) code that makes sense. Packages like co and coroutine became very popular with developers which took the advantage of asynchronous generator function wrappers. Transpilers like Babel also made use of asynchronous generator functions to allow using async/await keywords. This became a stepping stone for ES7 async/await.

Async/await

Even though transpilers used generator functions to create a syntactic sugar for async/await, ES7 Javascript introduced its own native implementation based on Promises. If you want to understand how it works, this article gives us an insight of what is really happening when we use async/await under the hood in V8.

This gets converted to the code below in V8's native implementation.

With async/await, writing async keyword before a function automatically returns us a promise and await keyword waits for the Promise to resolve before executing the lines next to it. We are not really creating a synchronous blocking code but just writing code in a way that just looks synchronous taking away the nested level code blocks.

Hope you now have a better understanding of async/await in Javascript. Thank you for reading this blog. If you liked it, do check out our other blogs and articles from Botsplash as well.

Subscribe to our newsletter... we promise no spam

Botsplash Logo
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.