1

I was reading an answer on StackOverflow here that explained how to use setTimeout to create a sort of recurring loop on a webpage. However, I am wondering why setTimeout requires an anonymous function to work. Consider the following code:

trainingTimer(60,0);

function trainingTimer(duration,c) {
    document.getElementById("timer").innerHTML = "Time left: "+(duration-c);
    if(duration==c) {
        alert("Time is up!");
    }
    else {
        window.setTimeout(trainingTimer(duration,c+1),1000);
    }
}

I wrote this based off the answer that I linked above, however when it runs it loops through all 60 trainingTimer calls at once, and immediately displays "Time left: 0" on my web page. However, if I modify

window.setTimeout(trainingTimer(duration,c+1),1000);

and wrap trainingTimer(duration,c+1) in an anonymous function like so

window.setTimeout(function() {trainingTimer(duration,c+1)},1000);

then the code works perfectly fine.

I am wondering why I have to wrap a named function inside an anonymous function in order for setInterval to work properly. Thanks for all the help.

4
  • 3
    trainingTimer(someargs) doesn't return a function, and setTimeout needs a function to execute. Commented May 13, 2014 at 20:16
  • @KevinB Technically it does not need a function... Commented May 13, 2014 at 20:26
  • i guess, kinda like window.alert() doesn't need an argument. Commented May 13, 2014 at 20:27
  • 1
    More on the lines that it can take a string and evaluate it. Commented May 13, 2014 at 20:28

3 Answers 3

5

This

window.setTimeout(trainingTimer(duration,c+1),1000); 

is the same as

var result = trainingTimer(duration,c+1);
window.setTimeout(result,1000); 

It takes the result of the executed method and assigns it.

And since training timer method returns nothing. Your code is basically this

trainingTimer(duration,c+1);
window.setTimeout(undefined, 1000); 
Sign up to request clarification or add additional context in comments.

Comments

3

The runtime has to evaluate the argument list passed to any function before it calls the function. The first thing you're passing to setTimeout in this code:

window.setTimeout( trainingTimer(duration,c+1), 1000 );

is the result of calling a function, not the function itself. Wrapping that in a function solves that problem.

The function doesn't have to be anonymous:

function callTrainingTimer() {
    trainingTimer( duration, c + 1);
}

// ...

window.setTimeout(callTrainingTimer, 1000);

works too.

Comments

3

Because that's how setTimeout works. It's first parameter is a function that you want it to run after x milliseconds.

When you do:

window.setTimeout(trainingTimer(duration,c+1),1000);

What you are doing is running trainingTimer immediately, and sending its return value to setTimeout.

You need to give it a function, that's why you do:

window.setTimeout(function() {
    trainingTimer(duration, c+1);
},1000);

There is a way to do it without a function, but it's NOT recommended.

window.setTimeout('trainingTimer(duration,c+1)', 1000);

This will use eval() to run the code. This works instead of passing a function, but it is not recommended. eval() is unsafe, do not use it.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.