0

This code crashes chrome:

 var ms = 1000;

 function wait(ms) {

     function _done() {
         done = true;
         alert('timer: ' + timer + ', done: ' + done);
         clearTimeout(timer);
     }

     var done = false;
     var timer;
     alert('starting timer');
     while (!done) {
         timer = setTimeout(_done, ms);
     }
     alert('wait done');
 }

Why? How do I get this right?

Bob Jones
  • 2,049
  • 5
  • 32
  • 60
  • 1
    When you set the timer variable, the while loop does not wait to execute the timer's code before it begins again, so you are essentially overwriting the timer on every loop and so it will never be run because it does not take longer than 1 second to complete your while loop. – Nunners Oct 02 '13 at 15:07

3 Answers3

0

When you are setting the timer variable inside the loop, the loop does not wait for the timeout to execute before the loop continues.

So you are overwriting your timeout every time the loop occurs and the code will never be executed because your while loop does not take longer than a second to run the code.

See here for a similar problem : Wait until a condition is true?

You code will essentially change to something like the following :

var ms = 1000;
var done = false;
var timer;

function _done() {
    done = true;
    alert('timer: ' + timer + ', done: ' + done);
    clearTimeout(timer);
    wait(ms);
}

function wait(ms) {
    if(!done) {        
        alert('starting timer');
        timer = setTimeout(_done, ms);
    } else {
        //Is Done...
    }
}

Once you call the wait function it will check to see if the done variable is true, if not it will call the _done function to set it to true. The _done function will then re-call the wait function to execute the condition again.

Community
  • 1
  • 1
Nunners
  • 3,047
  • 13
  • 17
  • 1
    This is not a good way to write javascript. This makes `wait` behave like 2 completely different functions. Instead, either `_done` should do whatever is in `wait`'s else, or `_done` should call a completely different function. – Corey Ogburn Oct 02 '13 at 15:22
  • True, if you look at the link I posted that is a much better way of describing what my code essentially does. I was just trying to mimic that code into pure JS using variable names that the OP would more likely understand. I agree it is not the best. – Nunners Oct 02 '13 at 15:25
0

There are a lot of fundamental problems here.

First, I'm assuming that somewhere not depicted in your code, you're actually calling the wait function by passing it ms.

It looks like you want the variables done and timer to be accessible in your function _done. To ensure that, you should init your variables before you define the function.

setTimeout is async. Javascript is single threaded unless you go out of your way to start up other threads (web workers). setTimeout will not freeze processing for ms amount of time. It adds an event that will run if nothing else is executing. Because it is not blocking, your while loop will loop again to create another timeout, and another... ad infinium. None of the many timeouts will interrupt the while loop because of its single threaded nature. It's more like the Windows Message Queue. Since _done doesn't interrupt and set done to true, it'll continually spin off more and more timeouts until an inevitable crash.

If you're wanting to delay code execution by a certain amount of time, you setTimeout once and execution will begin after that wait as long as nothing else is executing.

function _done() {
  alert('done!');
}

setTimeout(_done, 1000);

Another note, I don't think you have to clearTimeout for a timeout that has already timed out. Its only used to prevent a timeout from happening before it times out. This means that nine times out of ten, you can ignore the return value of setTimeout.

Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188
  • I fully understand your words, but I don't think you understand my problem. I simply want a synchronous wait function. To get this functionality with setTimeout, I have to nest each timeout within a parent and wind up becoming the snake eating itself. This seems like a gaping hole in javascript and I keep hoping that I am wrong about that. – Bob Jones Oct 03 '13 at 02:17
  • setTimeout is not capable of giving you a synchronous wait. No matter how you use it. While the thread is busy hurrying through your while loop, it will NEVER be interrupted by the async call to _done. Take a look at http://stackoverflow.com/questions/6921895/synchronous-delay-in-code-execution – Corey Ogburn Oct 03 '13 at 14:10
-1

you are missing the following line

timer = setTimeout(_done(), ms);

JSFIDDLE

Anand
  • 14,545
  • 8
  • 32
  • 44