Question

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.

Was it helpful?

Solution

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); 

OTHER TIPS

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top