This content originally appeared on Level Up Coding - Medium and was authored by Dylan Oh
Those who just got in touch with JavaScript might be confused when people say that JavaScript is a single-threaded and non-blocking programming language. You might be thinking how could one be single-threaded but non-blocking?
Single-Threaded
JavaScript is known to be single-threaded because of its property of having only one call stack, which some other programming languages have multiple. JavaScript functions are executed on the call stack, by LIFO (Last In First Out). For example, we have a piece of code like this:
const foo = () => {
const bar = () => {
console.trace();
}
bar();
}
foo();
And the call stack will have foo to enter into the call stack, then bar.
After bar() is done, it will be popped off from the call stack, followed by foo(). You will see an anonymous function underneath when printing out the stack trace, which is the main thread's global execution context.
This seems to be logical as JavaScript is a single-threaded language and there is only a single flow to execute all these functions. However, in the case that we are having some unpredictable or heavy tasks in the flow (for example making an API call), we do not want them to block the execution of the remaining codes (else users might be staring at a frozen screen). This is where the asynchronous JavaScript comes in.
Non-Blocking
Other than JavaScript Engine, we also have Web APIs, Callback Queue, and Event Loop to form JavaScript runtime in the browser. Let’s say we have a piece of code here:
console.log("1")
setTimeout(() => console.log("2"), 5000)
console.log("3")
“setTimeout” is a Web API function that will execute a callback function after a certain amount of time (in milliseconds, in this case, is 5000 milliseconds). When you execute this script, you will see that “1” and “3” are printed out instantly, and “2” is printed out around 5 seconds later.
This is what happened behind the scene:
The first console log is put into the stack and popped off after printing out “1” in the console. When setTimeout function is put into the stack, the callback function is set to await by this Web API function. The setTimeout function is then popped off the stack and the third console log enters. After finished execution, the third console log and the current global execution context are popped off from the stack.
When the callback function in setTimeout is finished awaiting, it will be entering to Callback Queue (or event queue) and waiting to be executed. The event loop facilitates and checks if the call stack is empty. If it is empty, a new global execution context is created and this call back function (console log out “2”) will then be put into the stack, executed, and popped off.
Just to add on, even if you are setting setTimeout to delay by 0 seconds, “2” will still be the last one to be printed out because as long as Web API is called, it will be put into the Callback queue and be placed onto stack only when the stack is empty.
I hope this gives you an idea of why JavaScript can be single-threaded and non-blocking at the same time.
Oh btw, if you still need a video explanation, here is a good resource:
What the heck is the event loop anyway? | Philip Roberts | JSConf EU
Do follow me if you would like to see more web development or software engineering-related content. Cheers!
JavaScript, Single-Threaded but Non-Blocking was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Dylan Oh
Dylan Oh | Sciencx (2022-06-12T17:04:51+00:00) JavaScript, Single-Threaded but Non-Blocking. Retrieved from https://www.scien.cx/2022/06/12/javascript-single-threaded-but-non-blocking-2/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.