JavaScript is Synchronous and Single Threaded. (Unfolding the Async Behaviour)
Guess what’s synchronous. JAVASCRIPT!

Every JS engineer comes to know about the async behaviour in javascript by some code like this.
var data = fetchData();console.log(data);
At first, he is bogged down by the fact that why does the console gave undefined as the output if my request resolved with the data because in other languages like PHP, java you are sure to get the data or something if you have fetched it somewhere above where you are outputting it.
To get this straight first let’s clear out a few things on how we are going to tackle this problem, understand how async works in js to the core and is js really synchronous.
In Order to get a basic understanding of what we are dealing with lets first find out what are we going to talk about in this post:
- What meant by asynchronous and synchronous.
- What is the Event loop?
- Final code to understand how to understand the execution order of any JS code.
What is meant by asynchronous and synchronous.
Sync: existing or occurring at the same time.
console.log(1);console.log(2);console.log(3);console.log(4);console.log(5);output:// 1 2 3 4 5
The code above is executed as expected in a synchronous manner, that is from top to bottom logging out all the data as expected.
Async: not existing or occurring at the same time.
Inorder to understand this async fashion in JS let’s look at this code snippet that uses setTimeout function.
function asyncConsole(time,value){setTimeout(function(){console.log(value);},time);}asyncConsole(200,1);asyncConsole(100,2);asyncConsole(400,3);asyncConsole(500,4);asyncConsole(300,5);output:// 2 1 5 3 4
Here the function though executed from top to bottom synchronously will console the output at different times thereby chaining the order of our console logs. You would argue that the one of the ways this should be done is the code should pause at the first asyncConsole and wait for the timer to finish and then move along the bottom side executing the code which would be synchronous but this approach has some down side for JS as it has some limitations.
The limitation is that no matter how many cores you have in your computer your JS program will only use a single core while executing the code and at any point of time only one task can be executed on that thread lying on the core. (That is the reason why JavaScript is single threaded)
So, if we pause the code at first asyncConsole then it would block the whole thread and all the operations running in our JS engine as all our operations are done on that single thread only. Hence we would proceed to the next line only after 200 ms.
Now as we know that time and memory are crucial resources in any system imagine what operations would you have been able to do in that 200 ms had that time not been blocked. You could have made and APIrequest, wrote some data to your database, fetched some more data, perform some calculations etc.
In order to tackle this problem modern js engines implement something called Event Loop.
The Event Loop
JavaScript has a concurrency model based on “event loop”. Every modern js engine implements event loop inorder to perform non blocking operations in javascript.
Consider Event loop as a loop that executes code untill there is no more code to execute.
This means that the code you write is not directly handed over to the event loop to execute. Now what event loop does is that when ever we execute a setTimeout function we ask our browser to do this “Whenever the timer gets over push the callback function to the a callback queue from which the event loop will take the callback to execute”.
Now you see that the setTimeout function was never a JS thing, it’s a browser API just like DOM API that we use. When ever you call setTimeout it’s actually the browser that takes what ever function you passed to it and then when the timer gets over it simply pushes the function to the “callback queue” from which the event loop picks up the function in an orderly fashion.
See here event loop does not have to know about anything. It’s only job is to take code handed to it and execute in the exact order in which it has received it.
setTimeout and such aren’t in the ECMAScript specification because they’re not JavaScript features. They’re features of the browser environment’s window object. Other environments (Windows Scripting Host, NodeJS, etc.) won’t necessarily have those features.
Browser features like XHR, setTimeout, setInterval, fetch, alert, prompt and all are not JSfeatures.
Now lets prove that js is synchronous in nature.
console.log(“1”);for(){// a loop that takes 5 seconds to complete}console.log(“2”);
VS
console.log(“1”);setTimeout(function(){},5000)console.log(“2”);
If you have something like this than 2 will be outputted exactly after 5 seconds as the loop takes 5 seconds to execute. Also imagine how unpredictable your code would be if the JScode you write would be async. The JS code will never be deferred in the first case where as the code in the second example the output 2 will be printed instantaneously because setTimeout is a browser feature that is differed and the function inside it is called after five seconds has been completed. Therefore certain browser features and third party libraries that access network or OSare async in nature so that in the meantime the request is getting fulfilled our JS engines has some task to perform. And if we already have a task to perform that is the “long for loop” then why we would defer it knowingly.
This is the reason why many devs generally say that JSin async in nature because they have been using functions like fetch, setTimeout, setInterval from a very long time with JS.
Describing JavaScript as asynchronous is perhaps misleading. It’s more accurate to say that JavaScript is synchronous and single-threaded.
How to understand order of execution of any code in JavaScript.
Now as we know the basics of how to understand what is going to be synchronous and what is going to be asynchronous let’s look at this code and take a deep dive into JS to understand the execution order of this code.
In order to guess the output you will need the following rules that JS engine uses.
- JS engine will run all the code in the global scope first.
- In order to run async functions the call stack must be empty
- Functions to be executed in the micro task queue are executed first.
- Functions in the callback queues are executed after callback queue.
Don’t sweat it if you don’t understand these rules we will take a look at it one by one.
Code in Global Scope: It is the code that you have written in the entry point of your file in the global scope.
Callback queue: It is a queue in which callbacks given to setTimeout or setInterval are put for the event loop to execute.
Microtask queue or Job Queue: This is a much newer queue. Previously all the functions that were to be called after resolving a network requests were put in the callback queue but now these callbacks are put into the micro task queue or the Job queue.
Now let’s execute the code line by line.
function blockThreadFor(numberMillis) {
var now = new Date();
var exitTime = now.getTime() + numberMillis;
while (true) {
now = new Date();
if (now.getTime() > exitTime)
return;
}
}function printData(data){
console.log(data.title)
};function printHello(){
console.log("Hello");
}setTimeout(printHello,0);let futureData = fetch("https://jsonplaceholder.typicode.com/todos/1"); // take 100 ms to return datafutureData.then((response)=>{
return response.json();
}).then(printData)blockThreadFor(1500);console.log("Hi");
Lets begin.

Function blockThreadFor simply blocks our main thread for some amount of time that we give to it.
Function printData prints the data that we give to it.
Function printHello prints “Hello”.
On the next line we start executing the function in the global scope.
We execute a broswer feature function called setTimeout and hands it printHello function to call after 0ms. As we know setTimeout is async in nature so after 0ms it will put the function printHello inside the Callback queue so that later when the condition meets it will be picked by the Event Loop and put on to the call stack to be executed.
So, will the printHello function run just after calling it? The answer is no, because according to the rules we have not executed all the code in the global scope so it will not be picked by the event loop.
On to the next line we simply make a get request and fetch some data and then chain a then function to convert the response to JSON and then call function printData that will print data for us fetched from the API. Fetch is again a broswer feature. We call it and move to the next line.
On to the next line we block the thread for 1500 ms. Meanwhile the response from the API comes back after 100 ms, but as we have blocked the thread for 1500 ms it will not be printed out.
After 1501 ms the thread will be unblocked and the data that we have fetched will be passed on to the function printData and the printData function will be put into the micro task queue to be picked up by the Event Loop.
So now will the printData function be executed? The answer is no. because still we have some global code to run and as per by the rule we cannot execute function from microtask queue if we have not executed all the code in our global scope.
Now we move to the last line of the code and we print “Hi” on the console.
After that event loop will figure out that all the code in the global scope has been executed so it’s time to check if we have any function in the microtask queue to be executed.
It will find out the printData function. So printData will be put on to the call stack and executed.
After the printData function is executed it will again check if there is any more code inside the micro task queue. As the micro task queue is empty it will move on to the callback queue and execute the printHello function which will console “hello”.
So the correct order of the console would be:
Hidelectus aut autemHello
How surprising it is that the function that we expected to execute in 0 ms was executed almost after 1500 ms, but by simply following the rules we were able to figure out the execution order of our code.
I hope that I have helped you to understand how and why Javascript is Synchronous and Single Threaded.