/    Sign up×
Community /Pin to ProfileBookmark

Why won’t setTimeout work for me in this code?

Hi all,

Here a snippet of code that I’ve written. When I’m debugging the code and it gets to the setTimeout command, it doesn’t appear to be calling the function again. Instead, it exits the function to the one that called it. Here’s the code:

[CODE]
function factorial(x)
{
factbuff = 1;
factidx = x;
factorialloop();

return factbuff
}

function factorialloop()
{
if (factidx > 0)
{
factbuff = factbuff * factidx;
factidx = factidx-1;

setTimeout(“factorialloop()”, 5);
}
}
[/CODE]

Any ideas why setTimeout isn’t working properly? I use setTimeout earlier in the script and it seems to work just fine, so I have no idea why it’s messing up here.

Thanks!

to post a comment
JavaScript

7 Comments(s)

Copy linkTweet thisAlerts:
@mrhooOct 08.2010 — You are returning before the timeout begins,

try this:
[CODE]function factorial(x){
factbuff= 1;
factidx= x;
factorialloop();
return factbuff
}
function factorialloop(){
if(factidx> 0){
factbuff= factbuff*factidx--;

setTimeout(factorialloop, 5);
}
else alert(factbuff)
}[/CODE]


The alert will show you the final value-

replace the alert with a callback function
Copy linkTweet thisAlerts:
@stojakapimpauthorOct 08.2010 — You are returning before the timeout begins,

try this:
[CODE]function factorial(x){
factbuff= 1;
factidx= x;
factorialloop();
return factbuff
}
function factorialloop(){
if(factidx> 0){
factbuff= factbuff*factidx--;

setTimeout(factorialloop, 5);
}
else alert(factbuff)
}[/CODE]


The alert will show you the final value-

replace the alert with a callback function[/QUOTE]


Hmm...not quite sure I follow as to why it is returning before the timeout begins. I've rewritten the code to only have one function and no global variables:

[CODE]function factorial(x,buff) {
if (x>0) {
buff = buff*x--;
setTimeout(factorial(x,buff),5);
}
else {
return buff
}
}[/CODE]


When I try to run this in the IE javascript debugger, it steps through the function just fine, yet when it's done with every iteration and finally gets to the "return buff" command, it then gives me an error that the setTimeout line is an invalid argument.

Is that because the "return buff" command is trying to return the value of buff to the setTimeout function, instead of the original function that called factorial() in the first place?

Thanks!
Copy linkTweet thisAlerts:
@mrhooOct 08.2010 — setTimeout(factorial(x,buff),5);[/QUOTE]

You can use a reference (factorial) in setTImeout,

but if you want to pass arguments you need a function-

[CODE]setTImeout(function(){factorial(x,buff)},5)[/CODE]

Your problem is you are not returning the value TO anywhere.

By the time the timeout runs, the function that called factorial has already returned with the first value set by factorial.

You need to call a function when you have found the final value.
Copy linkTweet thisAlerts:
@al-adly_foreverNov 21.2010 — setTimeout("functionName()", timeInMilliSeconds);

The function MUST be written in double quotes. I had this problem when I was making auto refresh in AJAX. I hope that helped you.

PEACE!
Copy linkTweet thisAlerts:
@rpg2009Nov 21.2010 — setTimeout("functionName()", timeInMilliSeconds);

The function MUST be written in double quotes. I had this problem when I was making auto refresh in AJAX. I hope that helped you.

PEACE! [/QUOTE]


Actually that's not recommended. It's inefficient as "functionName()" has to be evaluated at run time.

Edit: I'm not clued in with AJAX yet, so the quotes may have been necessary in your instance.

-----

SetTimeout set's an event and then continues to execute the succeeding code. The execution doesn't just wait at setTimeout.

So I guess something like this.

[CODE] function factorialloop(){
if (factIdx > 0){
factBuff *= factIdx--;
setTimeout(factorialloop, 15); // event set
} else {
callBackFn(factBuff, x);
}
// code continues to execute here
// a default of undefined is returned by the function.
// a bit later setTimeout does it's thing but it's all too late
} [/CODE]


I've nested the factorialloop function so that it can access factbuff etc via the scope chain. Therefore avoiding the use of global variables. Could more than likely be improved on.

[code=php]function factorial(x, cFN)
{

var factBuff = 1,
callBackFn = cFN || function(fact){ alert(fact) },
factIdx = x;
factorialloop();

function factorialloop(){
if (factIdx > 0){
factBuff *= factIdx--;
setTimeout(factorialloop, 15);
} else {
callBackFn(factBuff, x);
}
}
}

factorial(5, function(fact, x){
alert('Factorial of ' + x + ' = ' + fact);
}); // Factorial of 5 = 120

factorial(6); // 720[/code]


or to save creating the variables factor, callbackFn, factIdx each time.

[code=php]var factorial = (function (){

var factor, callBackFn, factIdx;

return function(x, CFN){
factor = 1;
callBackFn = cFN || function(fact){ alert(fact) };
factIdx = x;
factorialloop();

function factorialloop(){
if (factIdx > 0){
factor *= factIdx--;
setTimeout(factorialloop, 15);
} else { callBackFn(factor, x); }
}
}
}());[/code]



RLM
Copy linkTweet thisAlerts:
@KorNov 22.2010 — To avoid any misunderstanding or mistype regarding the quotes within a setTimeout() or setInterval() you should simply use an anonymous (or rather say an inner function) to trigger another function
<i>
</i>setTimeout([B][COLOR="Blue"]function(){[/COLOR][/B][I]someFunction(someArguments)[/I][B][COLOR="Blue"]}[/COLOR][/B],milliseconds)
Copy linkTweet thisAlerts:
@interfacetricksNov 22.2010 — Hmm...not quite sure I follow as to why it is returning before the timeout begins. I've rewritten the code to only have one function and no global variables:

[CODE]function factorial(x,buff) {
if (x>0) {
buff = buff*x--;
setTimeout(factorial(x,buff),5);
}
else {
return buff
}
}[/CODE]


When I try to run this in the IE javascript debugger, it steps through the function just fine, yet when it's done with every iteration and finally gets to the "return buff" command, it then gives me an error that the setTimeout line is an invalid argument.

Is that because the "return buff" command is trying to return the value of buff to the setTimeout function, instead of the original function that called factorial() in the first place?

Thanks![/QUOTE]


Yes. What's happening is the setTimeout is called, that puts a timed event in the queue. The code execution then continues past the setTimeout statement and reaches the end of the function. All javascript has now ceased, but a few milliseconds later the timer goes off and the function is called again.

This means the function is not called by the function, but is started because of the timer, and the function which set that timer has already finished. There's nothing to return a value to.

The way around this is to pass into the factorial function, another function that knows what to do with the result when it's finished. e.g. show it in a text box, or use it in another calculation.

Here is an example of how it can be done.

http://webinterfacetricks.com/factorial_timeout/

There is more explanation in the source code for how it works. Let me know if there's anything that's unclear.
×

Success!

Help @stojakapimp spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.7,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...