Single Threaded Model
JavaScript is a single-threaded programming language, which means that it can only execute one task at a time. This is because it has a single call stack and only one thread of execution. This is in contrast to multi-threaded programming languages, which can execute multiple tasks concurrently.
The single-threaded model in JavaScript has some advantages and disadvantages. On the one hand, it makes the language simpler and easier to learn, since there are no concerns about thread synchronization or race conditions. This also means that JavaScript is highly predictable since there is only one execution context and all code runs in the same order.
On the other hand, the single-threaded model can also be a limitation, since it means that long-running tasks can block the main thread and make the application unresponsive. To avoid this, JavaScript provides asynchronous programming mechanisms such as callbacks, promises, and async/await, which allow long-running tasks to execute in the background while the main thread remains responsive.
Another limitation of the single-threaded model is that it can make it difficult to write highly concurrent or parallel applications since all tasks must be executed sequentially on the same thread. However, there are techniques such as web workers and service workers that can be used to offload processing to separate threads or processes.
The open-source, WebAssembly, and JavaScript V8 engine from Google was created in C++. Among other applications, it is utilized in Chrome and Node.js.
This documentation is intended for V8’s design and performance enthusiasts as well as C++ programmers who want to use V8 in their applications. The ensuing documentation walks you through using V8 in your code, goes over some of its architectural specifics, and offers a set of JavaScript benchmarks to evaluate V8’s speed. This page serves as an introduction to V8.
The V8 engine of a Chrome browser is responsible for implementing JavaScript.
Two components make up the V8 engine:
- Heap Memory
- Call Stack
Memory Heap: This is where you allocate the space that your JavaScript program needs to run. Keep in mind that the memory heap is completely distinct from the heap data structures. It is the unoccupied space in your OS.
Call Stack: Your JS code is read and executed line by line within the call stack.
Considering that JavaScript is a single-threaded language, the program is run using just one call stack. The stack data structure described in Data structures is the same as the call stack. Stacks are First In Last Out, or FILO, as is common knowledge. Similar rules apply to the call stack, where a line of code is executed and moved out of the stack anytime it enters the stack. Due to the single call stack, JavaScript is a single-thread language.
JavaScript is a single-threaded language so we don’t have to deal with the complex situations that can develop in a multi-threaded environment, such as deadlock when running code on a single thread.
JavaScript is synchronous by nature because it is a single-threaded language. You might be wondering if it is possible now that you have utilized async calls in JavaScript.
Call Stack
Let me now go over the idea of an async call in JavaScript and how a single-threaded language makes it possible. Before I go into detail, let’s quickly go over why we need asynchronous or async calls. As we are aware, in synchronous calls, all work is carried out line by line, meaning that no matter how long one task takes to complete, the next task is always carried out after it. Due to this, the issue of resource and time waste develops. Asynchronous calls, which conduct additional tasks concurrently rather than waiting for one call to finish, solve these two issues. As a result, we employ async calls for performing tasks like image processing or sending network requests for things like API queries.
Now let’s return to the earlier query about how to use async calls within JS. A lexical environment, syntax parser, and execution context (memory heap and call stack) are all features of JS that are used to run JS code.
To make the concept very clearer, let’s use an example. Let’s say we wish to run the following piece of code in the JS run-time environment.
Example:
console.log(1);
setTimeout(() => {
console.log(2);
}, 1000);
console.log(3);
Output:
1
3
2
Since JavaScript is a single-threaded language, we should investigate why this isn’t happening since the output should be 1 2 3.
The first statement in the call stack is performed when JS tries to run the aforementioned program, printing 1 in the terminal and causing it to pop off of the stack. The second statement is now added to the call stack, but when it goes to execute it, it discovers that setTimeout() isn’t a part of JS, so it pops out the function and inserts the WebAPI to be executed there. The third statement is added to the stack and executed, printing 3 to the terminal because the call stack is once again empty.
The timeout function is carried out by the WebAPI in the downtime, and the code is added to the callback queue. The event loop determines whether or not the call stack is empty and whether any statements in the callback queue require constant execution. The statement is placed in the call stack as soon as the event loop determines that the call stack is empty and that there is something in the callback queue that needs to be processed. The call stack then runs the statement and prints 2 in the browser console.
You can get some benefits from the setTimeout() function for its asynchronous behavior. The asynchronous nature of javascript because it helps us to sort arrays easily. No more bubble, selection, merge, or quick sort algorithms. But here is the worst scenario of it.
Array Sort Using the setTimeout Function
Example:
let arr = [1,10,3,7,4,6,2,8,9,5];
arr.forEach(item => {
setTimeout(() => console.log(item), item);
})
Output: Sorted array.
1
2
3
4
5
6
7
8
9
10
When you use a large amount of the very largest number in your array or an array of very long lengths with big numbers, then it will wait for the next number to be sorted, this method waits for you until the number is equal to the counting milliseconds.
Example:
let arr = [1,10,3,700,4,6,2,8,9000,55,73,21];
arr.forEach(item => {
setTimeout(() => console.log(item), item);
})
Output:
1
2
3
4
6
8
10
21
55
73
700
9000
It will delay you 700 milliseconds for sorting the elements of the array is 700. And also take 9000 milliseconds for this item to be sorted.