Asynchronous Javascript in depth.
By: Nikhil Mohadikar
Tags: Asynchronous, Asyncawait, JavaScript, Async Functions, Promises

Coming from the synchronous code execution background like Ruby, I was always confused about how javascript executes code in an asynchronous way by remaining single threaded. This asynchronous code execution is really important and performance oriented way of computation nowadays which is being adopted by many languages. Although some languages still don’t support it, there are third-party libraries like ReactiveX which helps you to implement asynchronous workflows.

Before diving into the javascript asynchronous flow we will see what is the difference between synchronous code execution and asynchronous code execution.

Synchronous code execution.

Here in the above graphical representation, our main thread is executing code lines one after the other. After executing C2 it makes an API call and sits idle till we get a response and do response handling. Here the problem with this approach is that we are not executing C4 in the idle time even if C4 is completely independent of the response.

Idle time = Time taken by external API.

Asynchronous code execution

Here in the above graphical representation, the main thread is executing code lines one by one, after executing C2 it makes an API call and starts executing C4 even there is no response from the server. It simply defines response handling tasks which need to be executed when the response comes. Here it uses the CPU more effectively.

idle time = (Time taken by external API)-(Time taken by C4)

Here it looks like multiple threads are involved in the execution but the response handling part will be executed only when the current thread is free or it is done executing C4. If we get the response before C4 completes execution, then it will be kept on hold in message queue/event queue.

With the help of Event loop and message queue every non-blocking I/O is handled with the help of callbacks. Just take an example of browser events like the click event. We attach a callback function to click event whenever a task needs to be executed on click event. By taking advantage of this non-blocking I/O property of javascript we can utilize CPU in a better way. Let’s see practically how asynchronous code execution happens.

Event loop

Event loop in javascript is responsible to decide which thing should be executed next. Here it uses some data structures to store functions.

1:- Call stack (LIFO)

2:- Message queue (FIFO)

3:- Job queue (FIFO) (Introduced in ES6/2015).

Consider the above scenario. Let’s see the contents of Call stack and Message queue while executing each line.

Line 1

Here function main() is pushed in Call stack and message queue is empty

Line 2

Here inside main() function, console.log(“I’ll have my breakfast”) is pushed in Call stack which will be executed and popped out.

Line 3

Here setTimeout() is pushed in Call stack and executed. Here setTimeout() is setting a timer of 0 milliseconds to execute a task which will be pushed in Message queue when the timer starts.

Here console.log(“I’ll have my lunch”) is pushed in Message queue because it needs to be executed after some time. Even it needs to be executed in 0 milliseconds it is pushed in the Message queue to wait for its turn.

Line 6

Here while things in Message queue wait for their turn to be executed, next line i.e. console.log(“I’ll have my dinner”) is pushed in Call stack and executed and popped out after that.

Line 7

Here main() function is only remaining in Call Stack which will be executed and popped out of the stack.

Here Call stack is empty so event loop will decide to execute things from the Message queue in FIFO way. So here console.log(“I’ll have my lunch”) will be executed at last.

Difference between message queue and job queue.

In previous section you must be thinking about why job queue is not getting used. Are message queue and job queue both same? The answer is no. They are different and have different priority. Job queue is introduced in ES6 because of Promises. So the callbacks for promises are added into Job queue and all other callbacks are added in Message/Event queue. The priority for Job queue is high as compared to Message/Event queue.

Promises

With the introduction of promises in Javascript ES6 (2015), we can easily add asynchronous workflows to our javascript app without going to the callback hell ( http://callbackhell.com ).

Promises in javascript is a way of solving dependencies at the time of API calls etc. Just like a “Promise” we use our day to day life, Javascript promises works the same way.

Before diving into Javascript Promises, we will see the first fundamentals of Javascript Promises.