2

Since setTimeout crashes in while loops.

I don't know if there is a way to do it but I am trying to make one. This is how it looks so far.

<script>
var send = true;
function sendit()
{
    alert("test");
    return true;
}
while(true)
{
    if(send == true)
    {
        send = false;
        setTimeout(function(){
            if(sendit() == true) {
                send = true;
            }
        }, 5000);
    }
}
</script>

Is it possible this way?

Iamk Denok
  • 163
  • 1
  • 5
  • 13
  • 1
    This is perhaps an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) - what are you trying to solve? Your code here will block as soon as you set `send = false` as javascript is single threaded, and it's stuck within the `while(true)` loop at this point, with no chance for the timeout to ever occur. – James Thorpe Sep 04 '15 at 15:45
  • possible duplicate of : http://stackoverflow.com/questions/12996193/settimeout-inside-while-loop – Anand Dwivedi Sep 04 '15 at 15:45
  • @James Thorpe Well it isn't possible than, oh well... – Iamk Denok Sep 04 '15 at 15:48
  • 1
    @IamkDenok: Quite possibly you are just looking for setInterval() / clearInterval() for what you want to achieve. But it's hard to tell since we don't know what you wanted to achieve in your original code. If the answer linked above (by Anand) does not solve your problem, you might want to ask a different question explaining what you wanted to achieve in the first place. – Ma3x Sep 04 '15 at 15:49
  • @Ma3x setInterval() is what I was looking for, setInterval() is basically setTimeout in a while loop, thank you! – Iamk Denok Sep 04 '15 at 15:55

2 Answers2

4

You haven't explained what you want your code to do. If you want it to alert "test" every 5 seconds then you need this:

<script>
function sendit()
{
    alert("test");
    // Call sendit() the next time, repeating
    setTimeout(sendit, 5000);
}
// Call sendit() the first time
setTimeout(sendit, 5000);
</script>

No need for a loop, just get the function to schedule itself again.

foz
  • 3,121
  • 1
  • 27
  • 21
  • 1
    This is what I wanted, I also found out that setInterval() archives the effect. – Iamk Denok Sep 04 '15 at 15:56
  • 1
    Almost yes. setInterval() will allow `sendit()` functions to overlap (if they take a long time), whereas the code above will wait for `sendit()` to finish before waiting another 5 seconds. – foz Sep 04 '15 at 15:58
  • 1
    It would be better to say, that, since JS is single threaded, using setInterval with a function that takes longer than the specified interval will call the functions one after another right away (possibly freezing the browser). In this case calling setTimeout/setTimeout is better. However, if the function execution time is less than the interval and you need **a fixed delay between calls** then you should use setInterval. – Ma3x Sep 04 '15 at 16:07
  • @Ma3x Note that there are no guarantees in the spec of a fixed delay between calls. Chances are they will more or less be right, but both `setTimeout` and `setInterval` only guarantee a _minimum_ time before firing. – James Thorpe Sep 04 '15 at 16:16
  • @JamesThorpe: Yes, true. Both are subject to the minimum delay. I meant without the added delay from the function execution, which can add up significantly if the callback takes a few tens of milliseconds to execute. – Ma3x Sep 04 '15 at 16:20
  • Doesn't repeated recursion like this overflow the call stack? – gust Sep 03 '20 at 17:53
  • @gust Using `setTimeout` means it isn't recursing here, it is just scheduling the same function to be called at a later time. The second time around it will be called with a fresh stack, `setTimeout` returns immediately, the function exits, and the stack is cleaned up. – foz Sep 07 '20 at 08:08
0

My understanding is that what you're trying to do is the equivalent of Thread.sleep(5000) in a language like Java or C#. That functionality does not exist in JavaScript. If you want to do something some amount of time after your function's execution, put it in a timeout, but one way or another, that first function will still complete in the same frame unless you're performing an enormous amount of work.

Currently, your code is setting a timeout on sendit() a practically-infinite number of times before it returns. Since JavaScript is single threaded, even if 20 seconds passed, it still wouldn't have finished your function and couldn't start looking up timeouts it needs to process. What you should be doing is something like having the inside of the timeout set another timeout, and remove the enclosing while(true). That could allow for infinite, periodic behavior as I think you're looking for.

Katana314
  • 8,429
  • 2
  • 28
  • 36