Below content is an excerpt from my book – “JavaScript for C# developers“.
Consider the below code snippet, which has just 3 statements and seems to be simple but it is worth analysing it to understand how javascript works with respect to execution of asynchronous code.
During the execution phase, JavaScript engine starts executing your code from first statement till last statement. When JS engine executes the first statement at line 1, it prints ‘first statement’, as expected.
Second statement is bit tricky but it makes us to understand the intricacies of the asynchronous execution of javascript code.
setTimeout: This function has couple of parameters – first one is the function to be called and second parameter is the number in milliseconds after which the function has to be called. In the above code snippet, we’re declaring a function ‘sayHello’ and we intend the function to be called after 100 milliseconds.
This setTimeout function is not a normal function. This function interacts with the timer feature of its host environment (browser or NodeJS environment). Whenever we call setTimeout function, browser creates a timer with the number of milliseconds passed to the function. Once that time period (100 milliseconds, in our case) is elapsed, browser will pass the function to the callback queue (commonly referred as message queue)
The functions in the callback queue would be executed only when javascript engine completes its execution of all the code that are in the call stack. Once the call stack is empty, javascript engine would take the first callback function from the callback queue and executes them. After completion of this callback function, and if the current call stack is empty, it will take the next function and so on… This behaviour of polling the stack stack and if it is empty , processing of next message from callback/message queue is called ‘Event Loop’.
Following things happen when JavaScript engine executes the earlier code snippet
- ‘first statement’ gets printed at the console as a result of console.log statement at line 1.
- Then, javascript engine calls ‘setTimeout’ function which in turn creates ‘timer’ in browser. The information passed to the ‘timer’ are callback function(‘sayHello’ in this case) and time period after which the function has to be called(100 milliseconds in this case).
- JavaScript engine executes the next statement , printing ‘last statement’ as result of console.log statement at line 7.
- Once the 100 milliseconds time is elapsed, browser would send the callback function(‘sayHello’ in this case) to the callback queue.
- ‘Event loop’ would take the first message from the ‘callback queue’ and pushes on top of the call stack, only if the call stack is empty. If the call stack is not empty, javascript engine would execute all the statements till the call stack becomes empty and then only event loop would process the messages in the callback queue, if there is any. In this case, the call stack is empty (and there is no statements waiting to get executed), event loop would push the callback function ‘sayHello’ on top of the call stack.
- Function ‘sayHello’ would be executed and ‘hello’ would get printed in the console.
What would be the output of the below code snippet? The only difference between this code snippet and the earlier code snippet is the value of the second argument passed to the setTimeout function.
In previous code, we passed 100 milliseconds whereas in this code snippet, we pass 0(zero) milliseconds. Think for a moment and answer.
The output would be the same as the previous code snippet printing ‘first statement’ first and then ‘last statement’ and finally printing ‘hello’.
Here is what happens. Statement at line 1 results in printing ‘first statement’ in the console. In the second statement, ‘timer’ is created by the browser which has to be called after 0(zero) milliseconds. As the time period is 0 milliseconds, the function ‘sayHello’ is pushed to the callback queue immediately.
But the function ‘sayHello’ would NOT be called immediately. As stated earlier, ‘Event loop’ would process the messages in the callback queue only if the call stack is empty. But the call stack is not empty. The statement at line 7 is waiting to get executed. So, the javascript engine executes the statement at line 7, printing ‘last statement’ in the console and now only the call stack would be empty.
Now, ‘Event loop’ would process the messages in the call back queue, pushing the function ‘sayHello’ on top of call stack and printing ‘hello’ by executing ‘sayHello’ function.
I hope with this post, you’ve understood the asynchronous nature of javascript. Please let me know your thoughts in comments.