开发者

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/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜