JavaScript is a single thread language which makes it different from most of the languages. It is lack of multi-thread application’s abilities whereas it does not have to deal with complex problems such as deadlock or shared variable problems.
Single thread?
A single thread language will be lack of having concurrent processes running at the same time. That means, if you have a process which takes long time, then it will block other processes to run. For that reason, there is a timeout defined in browsers which waits for response of process. When the process does not response in that timeout, you will see a popup which asks you to kill process or not.
Do not run any business that will take long time on browser for not to block other functions.
So, How JavaScript simulate like it’s running our commands in a multi-thread environment? To answer this question let’s deep into how JavaScript environment.
JavaScript environment
Although JavaScript is a single thread language, we have a strong helper which is browser that has ability to manage complex operations. Web API, Callback Queue and Event Loop mechanisms are part of browsers.
Let’s dig into some details of each part.
Heap
Heap is the place (memory) where objects are stored when we define variables.
Stack
Stacks holds our function calls. On each new function call, it’s pushed on top of the stack. You can see your stack when you have an exception on JavaScript by stack trace.
Web API
Browsers have defined API’s which developers can be used to make complex processes such as to get location of visitor, GeoLocation is defined. A list of APIs are defined in the link which you can find in references (1).
Callback Queue
When a process finished its job, such as a xhr call, it’s dropped in a callback queue. Callback queue is triggered by event loop process after our stack is empty which means the process waits in that queue until our stack is empty. Once our stack has no function call, then a process is popped-out from callback queue and pushed in to stack.
Event Loop
A process which is responsible to check our stack and then trigger our callback queue continuously.
Example
What’s the expected output of above example? It starts with a console.log then continue with a setTimeout function which we wanted to run immediately(?) by giving a “0” timeout then another console.log.
setTimeout is something special. It’s not defined in ECMAScript specification. It is a Web API (2). It works asynchronously. The given timeout does not guarantee that function will work after the given time but guarantees that it will wait at least given time. So setTimeout(fn,0) will not start immediately but it will wait at least zero millisecond.
Let’s explain how it will behave when we run above code snippet.
- our first console.log(“Murat”) will be pushed to stack because we are making a function call.
- The variable will be saved in heap (memory)
- Because it’s not a async call, it’ll output given parameter
- First console.log function will be removed from stack, and heap will be empty
- setTimeout function will be called. So it’ll be pushed to stack
- It’s a async function and is a Web API function. It’ll be pushed to Web API box and setTimeout function will be removed from stack
- A timer in the background will be started to wait at least given amount of time to setTimeout.
- console.log(“Yusuf”) will be called and it’ll be pushed to stack and Yusuf will be stored in heap.
- It will output Yusuf. But at the same time, our event loop will continue checking stack’s status.
- After output of Yusuf, it’ll be removed from stack and heap.
- When the timer be sured that it’s waited at least given time, it’ll be pushed to callback queue (console.log(“Fatih”))
- Our event loop will trigger callback queue when the stack gets empty.
- Next, console.log(“Fatih”) will be put to stack
So, our output will be in the order of “Murat”, “Yusuf”, “Fatih”
References
- Web API list, https://developer.mozilla.org/en-US/docs/Web/API
- setTimeout specification, https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout