0

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) {
        alert(this.getString());
    } else {
        this.increment();
        setTimeout(this.loop(), 1);
    }
    }
}
2
  • Why are you doing this kind of processing on the client side, exactly? Commented Jun 24, 2011 at 1:55
  • @Karl Knechtel - Think distributed Commented Jun 30, 2011 at 14:28

6 Answers 6

3

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.

http://dev.w3.org/html5/workers/

Sign up to request clarification or add additional context in comments.

1 Comment

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.
2

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);

Comments

1

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.

Comments

1

why not have a loop checker using setInterval?

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

Comments

0

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.

Comments

0

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) {
  processItem(i);
}
done();

into

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.