Javascript is a single threaded beast, then how the heck asynchronous code execution works
You might have heard or read somewhere that javascript is single threaded programming language unlike other multithreaded programming languages like c++ or java.
Multithreading programming is the most common way of making any language concurrent and asynchronous which happens in java or c++.
If you have written javascript code then there are very fair chances that you might have written something like this.
console.log('before setTimeout')setTimeout(function(){
console.log('delayed by 500 milliseconds')
},500)console.log('after setTimeout')
the output will look like this:
before setTimeout
after setTimeout
delayed by 500 milliseconds
Despite the fact that javascript runs code line by line in a single thread then how this asynchronous behavior is possible. Other examples will be making any XMLHttpRequest which is also asynchronous.
This is a visual representation of how javascript engine (V8) makes it possible:
//index.jsconsole.log('start of index.js file');
function A(){
B();
console.log('fucntion A');
}function B(){
console.log('fucntion B')
}A();setTimeout(function(){
console.log('delayed by 500 milliseconds')
},500)console.log('end of index.js file');
//output
start of index.js file
fucntion B
fucntion A
end of index.js file
delayed by 500 milliseconds
Frames: Each function call creates a frame.
Stack: this is where frames are kept and executed.
Event loop: event loop is a piece of code which keeps checking. if the stack is empty and there is any callback in callback-queue it picks up and pushes it to stack.
Heap: this unstructured region of memory where Objects are allocated.
Web APIs: browser has set of web APIs which runs in their own thread or isolated from javascript runtime. setTimeout is also part of the web API. other examples will be XMLHttpRequest.
Event loop and Web APIs are vital for this asynchronous behavior.
now let’s see how this index.js file is executed line by line by js runtime(v8 engine):
v8 engine(js runtime) sees this piece of code at line 1:
console.log('start of index.js file');
and put it in stack ,execute and displays:
start of index.js file
v8 runtime picks up code from next line:
A();
and puts it in stack and start executing .since function A calls function B inside it so before finishing A , B is pushed to stack ,executed and displays:
function B
now after finishing B , B is popped out and control comes back to A. and code after fucntion call B() is excuted and displays:
function A
v8 runtime picks up code from next line:
setTimeout(function(){
console.log('delayed by 500 milliseconds')
},500)
since setTimeout is a part of sepearte web API and javascript runtime hand over it to web API section.
now magic happens this where asynchronous execution happens. here are two separate executions happening at the same time
1. js runtime picks up code from next line
console.log('end of index.js file');
puts it in stack and execute . and displays:
end of index.js file
2. while at the same time web API to which setTimeout belongs execute setTimeout.in this case wait for 500 missiliseconds and after 500ms put callback in Queue.
Note:in case of XmlHttpRequest it will fetch data from server and put callback in queue.
now after js runtime displays “end of index.js file”. it has nothing in the stack to execute. the stack is empty so event loops checks if there is anything in callback Queue .it finds one callback there and put it in the stack where v8 engine executes it and displays
delayed by 500 milliseconds
this is how asynchronous code execution works.
in nutshell, javascript runtime is very simple which is single threaded. but most of the heavy lifting is done through web APIs which run in their own thread/space. which makes concurrent execution possible. event loop helps to get back the result from the Queue where web API sends their results.
extra credit:
can you guess the output of this code? let me know in comments.
console.log("Hoddor")setTimeout(function(){
console.log("The winter is coming")
},500)while(true){
console.log("No ,it's not")
}
and what is there in the stack, Queue, and why the event loop is not effective here.