Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't setTimeout cancelling my loop?

I wondered how many times can a JavaScript while statement (in Chrome's console) can increment a variable in a millisecond, so I quickly wrote this snippet directly into console:

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

The problem is that it runs forever.
Why is this happening, and how can I solve it?

like image 727
rev Avatar asked Feb 09 '14 08:02

rev


People also ask

How do you stop a setTimeout loop?

To stop a setTimeout loop with JavaScript, we can call the clearTimeout function. let timeOutVar; const myFunc = (terminator = false) => { if (terminator) { clearTimeout(timeOutVar); } else { timeOutVar = setTimeout(myFunc, 1000); } }; myFunc(true); myFunc(false);

Does setTimeout block event loop?

Explanation: The for loop is a blocking statement, so while the setTimeout() is non-blocking. The loop creates 3 setTimeouts which go to the event loop and then to event queue.

What happens when if setTimeout () call with 0ms?

To explain: If you call setTimeout() with a time of 0 ms, the function you specify is not invoked right away. Instead, it is placed on a queue to be invoked “as soon as possible” after any currently pending event handlers finish running.

Is setTimeout guaranteed?

setTimeout is a guarantee to a minimum time of execution.


4 Answers

This comes back to the one-threaded nature of JavaScript1. What happens is pretty much this:

  1. Your variables are assigned.
  2. You schedule a function, to set run = false. This is scheduled to be run after the current function is run (or whatever else is currently active).
  3. You have your endless loop and stay inside the current function.
  4. After your endless loop (never), the setTimeout() callback will be executed and run=false.

As you can see, a setTimeout() approach wont work here. You might work around that by checking the time in the while condition, but this will tamper with your actual measurement.

1 At least for more practical purposes you can see it as single-threaded. Actually there is an so called "event-loop". In that loop all functions get queued until they are executed. If you queue up a new function, it is put at the respective position inside that queue. After the current function has finished, the engine takes the next function from the queue (with respect to timings as introduced, e.g., by setTimeout() and executes it.
As a result at every point in time just one function is executed, thus making the execution pretty much single threaded. There are some exceptions for events, which are discussed in the link below.


For reference:

  • https://stackoverflow.com/a/16757582/1169798

    Here a similar scenario was explained in more detail

  • https://stackoverflow.com/a/2734311/1169798

    A more in-depth description on when JS can be seen as single-threaded and when not.

like image 156
Sirko Avatar answered Oct 18 '22 22:10

Sirko


JavaScript is single-threaded so, while you are in the loop, nothing else gets executed.

like image 21
laurent Avatar answered Oct 18 '22 20:10

laurent


To keep the true speed of Chrome without having to constantly retrieve the time to calculate speed, you could try this JS code:

var start = new Date().getTime()
var i = 0
while(i<1000000)
{
    i++
}
var end = new Date().getTime()
var delta = end-start
var speed = i/delta
console.log(speed + " loops per millisecond")
like image 19
SyntaxLAMP Avatar answered Oct 18 '22 22:10

SyntaxLAMP


Javascript is single-threaded, that mean it runs only one instruction at a time, sequentially.

The event system, like in many other languages and library, is handle by an event loop. The event loop is basically a loop, which on each iteration check for message in the queue, and dispatch events.

In javascript (as in mot of languages implementing this pattern), the event loop is called when the stack is empty, that is to say, when all functions have returns, in other word, at the end of the program code.

Your "real" program look something like this behind the scene :

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

while(true) {
/*
 * check for new messages in the queue and dispatch
 * events if there are some
 */
  processEvents();
}

So the message from the clock saying timeout is over is never processed.

More info on the event loop on : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop


Of course it is a bit more complex, check here those examples : Is JavaScript guaranteed to be single-threaded? (tl;dr: In some browser engines, some external events are not dependent on the event loop and are immediately fired when they occur, preempting the current task. But this is not the case with setTimeout, which just add a message to the queue and never fires immediately.)

like image 4
jillro Avatar answered Oct 18 '22 20:10

jillro