Take the 2-minute tour ×

I am trying to create a page which needs to preform lots of loops. Using a while/for loops cause the page to hang until the loop completes and it is possible in this case that the loop could be running for hours. I have also tried using setTimeout, but that hits a recursion limit. How do I prevent the page from reaching a recursion limit?

var looper = {
    characters: 'abcdefghijklmnopqrstuvwxyz',
    current: [0],
    target: '',
    max: 25,
    setHash: function(hash) {
    this.target = hash;
    this.max = this.characters.length;
    getString: function() {
    string = '';
    for (letter in this.current) {
        string += this.characters[this.current[letter]];
    return string;
    hash: function() {
    return Sha1.hash(this.getString());
    increment: function() {
    this.current[0] += 1;
    if (this.current[0] > this.max) {
        if (this.current.length == 1) {
        this.current = [0, 0];
        } else {
        this.current[1] += 1;
        this.current[0] = 0;
    if (this.current[1] > this.max) {
        if (this.current.length == 2) {
        this.current[2] == 0;
        } else {
        this.current[3] += 1;
        this.current[2] = 0;

    loop: function() {
    if (this.hash() == this.target) {
    } else {
        setTimeout(this.loop(), 1);
share|improve this question
Why are you doing this kind of processing on the client side, exactly? –  Karl Knechtel Jun 24 '11 at 1:55
@Karl Knechtel - Think distributed –  AJ00200 Jun 30 '11 at 14:28

6 Answers 6

up vote 3 down vote accepted

setInterval is the usual way, but you could also try web workers, which would be a more straightforward refactoring of your code than setInterval but would only work on HTML5 browsers.


share|improve this answer
Yes, I have used web workers before in experimental code and may use them later in this project. But right now it needs to be cross-browser. Thanks for the advice. –  AJ00200 Jun 24 '11 at 1:50

Your setTimeout is not doing what you think it's doing. Here's what it's doing:

  1. It encounters this statement:

    setTimeout(this.loop(), 1);
  2. It evaluates the first argument to setTimeout, this.loop(). It calls loop right there; it does not wait for a millisecond as you likely expected.

  3. It calls setTimeout like this:

    setTimeout(undefined, 1);

In theory, anyway. In reality, the second step never completes; it recurses indefinitely. What you need to do is pass a reference to the function rather than the returned value of the function:

setTimeout(this.loop, 1);

However, then this will be window on the next loop, not looper. Bind it, instead:

setTimeout(this.loop.bind(this), 1);
share|improve this answer

setInterval might work. It calls a function every certain amount of milliseconds.

For Example

 myInterval = setInterval(myFunction,5000);

That will call your function (myFunction) every 5 seconds.

share|improve this answer

why not have a loop checker using setInterval?

var loopWorking = false;
function looper(){
    loopWorking = true;
    //Do stuff
    loopWorking = false;
function checkLooper()
    if(loopWorking == false)
setInterval(checkLooper, 100); //every 100ms or lower. Can reduce down to 1ms
share|improve this answer

If you want to avoid recursion then don't call this.loop() from inside of this.loop(). Instead use window.setInterval() to call the loop repeatedly.

share|improve this answer

I had to hand-code continuation passing style in google-code prettify.

Basically I turned

for (var i = 0, n = arr.length; i < n; ++i) {


var i = 0, n = arr.length;
function work() {
  var t0 = +new Date;
  while (i < n) {
    if (new Date - t0 > 100) {
      setTimeout(work, 250);

which doesn't hit any recursion limit since there are no recursive function calls.

share|improve this answer

Your Answer


