What is a thread?
The age old definition of a thread in programming says, "A thread is a lightweight process ". What's a process? "A process is a program in execution". To simplify things, a piece of code you write and save somewhere on your hard disk is nothing but a program lying idle in your computer. You execute that piece of code and there it becomes a process (process of providing an environment for your dead program to run) running in your system, eating some resource.
A thread is very similar to your running process, it is basically a sub-process that exists within a main process and has access to the resources allocated to the process.
Let's say your program does three things :
1- Fetch some file from some server
2- Convert its MIME type
3- Send it over an email to your friend
You have an option to do this synchronously in a single thread (one after another task) or create separate threads for selected tasks (usually heavier tasks). Two newly created threads within the same process simply represent two new environments within the main process for two different parts of your code to run. You guessed the benefit, faster processing.
Why is JavaScript single-threaded?
You must already have read somewhere, "JavaScript is single-threaded because it has only one call stack". Never mind if you did not come across this statement before, now you did. The call stack is just a tool which the JavaScript interpreter uses to track the sequence of code execution. When the interpreter encounters a function call, it wraps the function code in something called an Execution Context and throws it on top of the stack, when the function finishes executing, its Execution Context pops out of the stack.
Now unlike languages like Java, JavaScript does not implement threads. You can equate "Execution Context" in JavaScript to threads (an environment with resources to run your code), that we discussed earlier. The stack can have multiple Execution Contexts but only the one on the top of the stack executes and unless it pops out of the stack other Execution Contexts cannot execute. You guessed it, JavaScript has a single Call Stack and at a time only one Execution Context can execute in the Call Stack. Hence, traditionally single-threaded.
How does JavaScript process Asynchronous code?
That's a very obvious question to ask when we already concluded JavaScript's single-threaded nature. It's important to understand that JavaScript Runtime is just another process running in the browser. To be precise, running in the main thread of your browser. Every browser implements multi threading in its own way.
Out of many possible threads in the browser's process, a few are :
1- The main thread
2- Parser thread
3- Web worker thread
4- Garbage collector thread
5- Statistics collector thread
etc..
The main thread is responsible for :
1- Processing user events
2- Painting the DOM
3- Running the JavaScript Runtime
Now the simple answer to the big question. JavaScript does not handle asynchronous code all by itself. The browser comes to its rescue with its multi-threaded nature. When a function along with its Execution Context is put in the stack for execution, if found synchronous, it executes and pops out. What happens if the function is asynchronous (AJAX, DOM manipulation, setTimeOut() etc..) ? JavaScript Runtime, pops it out immediately, delegating the task of its execution to the Browser's APIs. That's how we get an illusion of JavaScript being Asynchronous and Single-threaded at the same time.
Next Read
We will talk more about how JavaScript uses Browser's APIs to get its work done. We shall also look into the process of code execution in the JavaScript Runtime.