Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

js while(true){} blocks event loop

setInterval(function(){console.log("hello")},2000);
while(true){}

"hello" never gets printed.

I think event loop runs in a different thread, but here it seems like 'while loop' is preventing the 'event loop' from execution. Can somebody put some light on this?

like image 258
Jagga Avatar asked Jun 03 '17 11:06

Jagga


2 Answers

You have to understand

How browser internally does setTimeout?

I will explain in brief.

To learn more about this

Here is more detail explanation of event loop by Philip Roberts in jsconf2014

Philip Roberts: What the heck is the event loop anyway?

Also, to see this process in action there is a great tool take a look at loupe

To understand that you have to know about event queue in javascript. There are event queues implemented in browser. Whenever an event get triggered in js, all of these events (like click etc.. ) are added to this queue. When your browser has nothing to execute it takes an event from queue and executes them one by one.

Now, when you call setTimeout or setInterval your callback get registered to an timer in browser and it gets added to the event queue after the given time expires and eventually javascript takes the event from the queue and executes it.

This happens so, because javascript execution is single threaded and they can execute only one thing at a time. So, they cannot execute other javascript and keep track of your timer. That is why these timers are registered with browser (browser are not single threaded) and it can keep track of timer and add an event in the queue after the timer expires.

same happens for setInterval only in this case the event is added to the queue again and again after the specified interval until it gets cleared or browser page refreshed.

Note

The delay parameter you pass to these functions is the minimum delay time to execute the callback. This is because after the timer expires the browser adds the event to the queue to be executed by the javascript engine but the execution of the callback depends upon your events position in the queue and as the engine is single threaded it will execute all the events in the queue one by one.

Hence, your callback may sometime take more than the specified delay time to be called specially when your other code blocks the thread and not giving it time to process what's there in the queue.

And as I mentioned javascript is single thread. So, if you block the thread for long.

Like this code

while(true) { //infinite loop 
}

Your user may get a message saying page not responding.

And here, your setTimeout event will never execute.

like image 176
Nadir Laskar Avatar answered Oct 29 '22 10:10

Nadir Laskar


Non-blocking while loop:

let done = false;

setTimeout(() => {
  done = true
}, 5);

const eventLoopQueue = () => {
  return new Promise(resolve => 
    setImmediate(() => {
      console.log('event loop');
      resolve();
    })
  );
}

const run = async () => {
  while (!done) {
    console.log('loop');
    await eventLoopQueue();
  }
}

run().then(() => console.log('Done'));
like image 40
AlbertS Avatar answered Oct 29 '22 10:10

AlbertS