DEV Community 👩‍💻👨‍💻

Sarthak
Sarthak

Posted on

Javascript Concurrency Model

Concurreny Model in Javascript

In this article we are going to find out how Javascript implements concurrency and what is event loop and much more...

So first of all what we all know about Javascrpit is that it is -

  1. single-threaded which means 2 statements cannot be executed simultaneously,
  2. non-blocking which means execution of some code should not stop the execution of program because its too slow making the browser unresponsive,
  3. asynchronous which means that 2 or more tasks can be done simultaneously,
  4. concurrent means multiple computations can happen at same time.

Since Javascript is single-threaded, then how does it execute statements asynchronously?

Example code:

    console.log("Hello");
    setTimeout( () => {
        console.log("Hello inside setTimeout");
    }, 1000);
    console.log("Bye");
Enter fullscreen mode Exit fullscreen mode

After executing above statements, browser prints "Hello" and "Bye" first and then "Hello inside setTimeout".

To find out the answer we need to learn Event Loop first...

Event Loop Visualisation

Alt Text Fig: Image src: freecodecamp.org

Heap: This is where memory allocation for all your variables take place.

Stack: This is where all the javascript code is pushed and gets executed line by line and is popped out after its execution. Javascript maintain the order of execution contexts using this stack only. It is also known as program stack or execution context stack.

Callback Queue: This is the place where all the asynchronous code goes. The callback functions from setTimeout, setInterval, HTML events and ajax requests are pushed into this queue when they are ready for execution.

Event Loop: The main function of event loop is to check the program stack and find if it is empty. If the stack is empty, then it checks the callback queue. If the callback queue is not empty then it pushes the code block from callback queue to main stack and executes it sequentially.

Now lets try to understand what is happening when the above program is getting executed.

  1. The program execution starts. Since Javascript is single threaded only 1 line can be executed at a time.
  2. So, First line of code is pushed onto stack.
  3. The console.log is executed printing "Hello". So this line is now popped out of stack.
  4. Now next line to be executed is setTimeout and it gets pushed onto stack. Now the javascript runtime can only execute single statement but the browser comes with a whole lot of other things which are web apis. This is when concurrency comes into picture. Now on the execution of setTimeout, a call to setTimeout api is made and the setTimeout is now popped of from stack.
  5. The third statement is pushed onto stack and then executed. This prints "Bye" as output.
  6. Now when the setTimeout api ( and all other apis ) are completed, the callback is pushed into callback queue simultaneously. These apis cannot interact directly with the stack.
  7. Now is the time when event loop comes into picture. Event loops jobs is to monitor call stack and task queue. If the call stack is empty, it has to take the first thing from the callback queue and push it onto the stack. So now callback from the timeout is pushed onto the stack which then gets executed and prints "Hello inside setTimeout".

Exercise Time

const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log("timerStart");
    resolve("success");
    console.log("timerEnd");
  }, 0);
  console.log(2);
});
promise.then((res) => {
  console.log(res);
});
console.log(4);
Enter fullscreen mode Exit fullscreen mode

The output of the above code snippet is -
1

2

4

timerStart

timerEnd

success

Brief Explanation of output

  1. First of all console.log(1) is executed printing "1".
  2. Then setTimeout is executed and anonymous function is pushed to Stack and executed.
  3. Then console.log("timerStart") is executed printing "timerStart".
  4. Then resolve() is executed thus resolving the promise and the anonymous function from line 66 - 68 is added to callback queue.
  5. Then console.log(2) is executed.
  6. Then console.log(4) is pushed to stack and executed.
  7. Lastly, after the stack is empty the anonymous function from callback queue is pushed to stack and executed.

Some Important facts about event queue-

  1. All the asynchronous code is always executed after the execution of main stack code.
  2. That is the good part: Your current statements/functions in the stack will run to completion. Async code can not interrupt them. Once your async code is ready to execute, it will wait for main stack to be empty.

When will you utilize event loop?

  • When you need to do heavy computation which is not required sequentially. In such a case, you would not want to block the main thread.
  • When a certain piece of code is to be executed after all the other functions and statements are executed.

Top comments (0)

In defense of the modern web

I expect I'll annoy everyone with this post: the anti-JavaScript crusaders, justly aghast at how much of the stuff we slather onto modern websites; the people arguing the web is a broken platform for interactive applications anyway and we should start over;

React users; the old guard with their artisanal JS and hand authored HTML; and Tom MacWright, someone I've admired from afar since I first became aware of his work on Mapbox many years ago. But I guess that's the price of having opinions.