How to write a factorial function in Javascript using setTimeout or setInterval
I asked a question a couple weeks ago about using setTimeout for a factorial function, but it was unfortunately with an unregistered account and I never got a complete answer.
My main issue is that I'd like to write a function that calculates the factorial of a number but uses the setTimeout or setInterval commands. The impetus behind this is to reset a counter the IE uses so as to avoid a long-running script warning. Currently, the factorial function I have is:
function factorial(n) {
return 0 === n || 1 === n ? 1 : n * factorial(n - 1)
}
In my other post, jsumners was kind enough to provide me with code that tried to use setTimeout periodically when calculating a factorial:
function factorial(x) {
executions++;
if (x > 1) {
if (executions % 20 === 0) {
return (function() {
var y = x;
setTimeout(function(y) { return y*factorial(y-1); }, 1);
});
} else {
return x*factorial(x-1);
}
} else {
executions = 0;
return 1;
}
}
In the above code, it should theoretically use the setTimeout command to perform the next multiplication when the number of elapsed executions is a factor of 20 (mod 20). Unfortunately, the code does not work, and what happens is that if trying to calculate the factorial of a number greater than 20, then the result is NaN. If the number is less than 20, then the answer is correct.
Does anyone know of a solution to this or anot开发者_如何转开发her way to calculate a factorial by using the setTimeout or setInterval commands?
Thanks!
It's because you're specifying y
as a parameter which is undefined
when executed because it's not passed in, you can fix it by change this:
setTimeout(function(y) { return y*factorial(y-1); }, 1);
To this:
setTimeout(function() { return y*factorial(y-1); }, 1);
However, it'll still be NaN
because here:
return (function() {
var y = x;
setTimeout(function() { return y*factorial(y-1); }, 1);
});
You're still returning a function, not a number that can be multiplied, so you still can't use a setTimeout()
in this manner. You could pass a callback that executes when everything's done, but you can't have it recurse and return to a caller like this.
The callback style factorial with each recurrent step scheduled with setTimeout is:
// private helper function (recurrency with accumulation)
function _factorial(acc, n, callback){
if(n==0){
callback(acc);
}else{
var callback_wrapper = function(result){
callback(result);
};
setTimeout(function(){_factorial(acc * n, n-1, callback_wrapper)}, 10);
}
}
// public function
function factorial(n, callback){
_factorial(1, n, callback);
}
// usage example
factorial(10, function(result){console.log(result)});
-- Cheers, Lambder
http://lambder.com/
http://vanadiumJS.com/
精彩评论