paint-brush
The Implications of Javascript being a Single-threaded Language by@sharjeelsidd
1,704 reads
1,704 reads

The Implications of Javascript being a Single-threaded Language

by SharjeelAugust 28th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

The most important thing to understand here is the path of the cyber attack – its vector. Let's take a closer look at various problems associated with OpSec and its implementation to modern life. Never reuse passwords, especially for accounts with personally identifiable and sensitive information. Use different emails and different strong passwords. Never link phone numbers to crypto platforms. Use trusted multiple e-sims if you have to link the phone. Never store your seed phrase digitally. Use YubiKey keys on the Yubi key to be considered more secure than phone-based OTP options.

Company Mentioned

Mention Thumbnail
featured image - The Implications of Javascript being a Single-threaded Language
Sharjeel HackerNoon profile picture


If you have been using Javascript for a while then you may come across the phrase describing it to be a ‘single threaded’ language.


What does that mean?


Javascript runs on a V8 engine with a memory heap and a call stack. JS being single-threaded means only one statement is executed at a time. Before we dive into what running on a single thread means, I want to first go over the terminology that will you will encounter.


I will try to explain this as simply as possible. To understand this better, you need to understand a Data Structure known as Stack (Last In, First Out).


Synchronous (or sync) execution usually refers to code executing in sequence. In sync programming, the program is executed line by line, one line at a time. Each time a function is called, the program execution waits until that function returns before continuing to the next line of code.


For example, you are calling someone and you’re waiting for them to pick up so that you can talk to them. You’re not doing any other thing until they pick up the phone.

You fulfill the request sequentially.


const one() => {
     const two() => {
       console.log('5');
 }
    two();
}


So, what happens under the call stack?


The call stack’s job is to fill in the instructions and pop an instruction as it gets executed.

Javascript is a single-threaded language that can be non-blocking. Single-threaded in the sense that it has only one call stack. Whatever is at the top of the call stack is run first.


In the above program, functions are run sequentially.


What if we have a function that is required to do heavy lifting? Should we let the user wait till that process is over?


const one() {
      console.log("Hello");
}
const two () {
    for(i=0; i<= 100000000000000000000000; i++){
}
const three(){
       console.log("World");
}
one();
two();
three();


Consider the above example, what if our second function has to loop through huge numbers, Does this means three() has to wait till two() is executed? Technically, Yes!


In our small example, it may not mean much but if we have to implement it in a real project then the users may not be able to do anything until the first process is finished.


Asynchronous (or async) execution refers to execution that doesn’t run in the sequence it appears in the code. In async programming, the program doesn’t wait for the task to complete and can move on to the next task.


To put it an example: You call someone and while you’re waiting for them to pick up the phone, you’re also running errands.


Different languages have different ways to implement asynchronous execution. The most popular is through Multi-threading.


Java implements multi-threading by creating a child thread that does its own separate execution and then merges back with the parent thread.


This, however, can run into a problem known as Deadlock, which can be dealt with by various deadlock prevention mechanisms.


Since we are concerned about implementing asynchronous execution in Javascript, Let’s see how that can be done


Try running this on the console and see what happens.


console.log('1');
setTimeout(()=> {
console.log('2')
}, 3000);
console.log('3');


You may see 1 3 and with a brief delay 2 shows up. Why is this happening?

In a nutshell, the asynchronous implementation in Javascript is done through a call stack, call back queue and Web API, and event loop.


Call stack’s job as we have seen earlier is to check what instruction is at the top of the stack and execute it. If there is an instruction like setTimeout() that requires extra time to execute then call stack will pop that out and send it to Web API.


The job of an event loop is to continuously check if an event occurred, like a mouse click or keyboard stroke so that it can send that to the call stack. Of course, your mouse click will be given higher priority for execution than an image load.


In Javascript, All instructions are put on a call stack. When the stack arrives at setTimeout, the engine sees it as a Web API instruction and pops it out, and sends it to Web API. Once the Web API is done with the execution, it will arrive at the callback queue.


The engine checks if the call stack is empty. If it is empty, then we check the callback queue which has the instruction setTimeout in it. The callback queue sends it to callback stack and the instruction is executed.


The other way to think about this is when you make an API request. Say for example your website needs to fetch an image from a server. Should your website refuse to load other parts till the image arrives? That would be a bad user experience.


When the call stack sees it needs to fetch an image, it pops and sends it to Web API and continues executing the remaining functions.


The response to the image request is stored in the call stack queue.


When the call stack is empty, the event loop which is continuously running looks over the Call stack queue if it has anything. If it does, in our case the response of image request. It puts over the call stack and executes the instruction.


The benefit of this procedure is JavaScript need not worry about how many cores or nodes a CPU is running on. There is only a single call stack for this implementation.



Also published here.