1

I'm not 100% sure how setTimeout works in JavaScript. Say I have something like this:

$(document).ready(function() {           
    testTimeout();        
});

function testTimeout() {
    alert("testing timeout");
    setTimeout(testTimeout, 5000);
}

This would display a popup window every 5 after the page is ready. What would happen if then I called testTimeout from a button click?

$("#button").click(function() {        
    testTimeout();
}); 

Would the button click call testTimeout and add another timeout every 5 seconds? Or, would the button click reset the timeout from when the button was pressed? The reason I am asking is because I would like to design something like this where I can pass a parameter to my timeout function. When the web page starts up, I have a default parameter. However, if I press a button, I would like my timeout function to be called right away and every 5 seconds after with my new parameter. But, I don't want the timeout function with the old parameter to continue repeating. How can I achieve this? Any help and understanding would be greatly appreciated.

6
  • 1
    "This would display a popup window every 5 after the page is ready. " No it wouldn't, it would show an alert repeatedly with no delay. Commented Nov 5, 2014 at 15:22
  • Your alert has a syntax error Commented Nov 5, 2014 at 15:23
  • Really? That doesn't seem to be the case for me? Commented Nov 5, 2014 at 15:24
  • OP editted, a quote and a parentheses was edited (see your answer, you'll see it) Commented Nov 5, 2014 at 15:26
  • do you want to reset the timeout when you click the button or just do nothing? Commented Nov 5, 2014 at 15:48

3 Answers 3

2

This would display a popup window every 5 after the page is ready.

No it wouldn't, it would show an alert repeatedly with no delay and/or cause a "too much recursion" error, because setTimeout(testTimeout(), 5000) calls testTimeout and passes its return value into setTimeout, just like foo(bar()) calls bar and passes its return value into foo.

If you remove the ():

function testTimeout() {
    alert("testing timeout");
    setTimeout(testTimeout, 5000);
    // here --------------^
}

Then it would do that.

What would happen if then I called testTimeout from a button click?

You'd end up with the function being called twice as often (more than once every 5 seconds), because every time you call it, it reschedules itself. A third time would make it more frequently still (three times/second), and so on.


If you want to avoid that, one option is to remember the timer handle and cancel any outstanding timed callback if you call the function before then:

var handle = 0;
function testTimeout() {
    clearTimeout(handle); // Clears the timed call if we're being called beforehand
    alert("testing timeout");
    handle = setTimeout(testTimeout, 5000);
}

(I initialized handle with 0 because calling clearTimeout with a 0 is a no-op.)

Sign up to request clarification or add additional context in comments.

4 Comments

This script is a recursive nightmare D:
@SterlingArcher: It was as originally written, yeah. Without the () it's a fairly common idiom for a repeated action (the other being, of course, setInterval).
Sorry, I forgot to remove the () from setTimeout. So, how do I prevent it from rescheduling itself? I only want one timeout every 5 seconds. But, when I click a button, I would like to change the parameter being used in the timeout function.
@user3781214: You can do that by saving the timer handle and using clearTimeout, I've added that to the above.
1

Have you tried to asign variable to your setinterval;

var foo = setTimeout(testTimeout(), 5000);

and then when right event comes just destroy that variable.

clearInterval(foo);

And now you can asign it again...

Comments

-1

In your case it would simply repeat endlessly, because you're executing the function instead of passing the reference. You should do it like this:

function testTimeout() {
    alert("testing timeout)";
    setTimeout(testTimeout, 5000);
}

Note the missing braces after testTimeout. This tells setTimeout to execute that function, instead of the result of that function, which is how your original code behaved.

" I would like my timeout function to be called right away and every 5 seconds after with my new parameter. But, I don't want the timeout function with the old parameter to continue repeating "

In order to achieve what you're trying to do you should remove the timeout:

var timeoutId;
function testTimeout() {
    alert("testing timeout)";
    clearTimeout(timeoutId );
    timeoutId = setTimeout(testTimeout, 5000);
}

Notes:

  • You can stop the previous timeoutI from firing by catching the id returned from the setTimeout method and passing that to the clearTimeout method

2 Comments

you can clearTimeout too, so there is no need to resort to intervals
True, I forgot he was calling the same method, which trigger anothers setTimeout

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.