views:

71

answers:

1

Hi all,

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 another way to calculate a factorial by using the setTimeout or setInterval commands?

Thanks!

+4  A: 

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.

Nick Craver
Thanks for breaking down the code for me and letting me know what the issue was. That said, I should say that I'm an amateur to Javascript, so I'm not quite sure how to to implement a callback as you suggested. Do I get rid of the 'return' syntax and instead just have the setTimeout command, and then once the multiplier gets down to 1 I then call a callback which returns the answer? Thanks again for the help.
jrenfree