views:

748

answers:

2

I have written a javascript function that uses setInterval to manipulate a string every tenth of a second for a certain number of iterations.

function timer() {
    var section = document.getElementById('txt').value;
    var len = section.length;
    var rands = new Array();

    for (i=0; i<len; i++) {
        rands.push(Math.floor(Math.random()*len));
    };

    var counter = 0
    var interval = setInterval(function() {
        var letters = section.split('');
        for (j=0; j < len; j++) {
            if (counter < rands[j]) {
                letters[j] = Math.floor(Math.random()*9);
            };
        };
        document.getElementById('txt').value = letters.join('');
        counter++

        if (counter > rands.max()) {
            clearInterval(interval);
        }
    }, 100);
};

You can get an idea of what the purpose is here:

http://clients.okay-plus.com/datherrien/randomInterval.html

Instead of having the interval set at a specific number, I would like to update it every time it runs, based on a counter. So instead of:

var interval = setInterval(function() { ... }, 100);

It would be something like:

var interval = setInterval(function() { ... }, 10*counter);

Unfortunately, that did not work. It seemed like "10*counter" equals 0.

So, how can I adjust the interval every time the anonymous function runs?

+1  A: 

Use setTimeout() instead. The callback would then be responsible for firing the next timeout, at which point you can increase or otherwise manipulate the timing.

EDIT

Here's a generic function you can use to apply a "decelerating" timeout for ANY function call.

function setDeceleratingTimeout( callback, factor, times )
{
  var internalCallback = function( t, counter )
  {
    return function()
    {
      if ( --t > 0 )
      {
        window.setTimeout( internalCallback, ++counter * factor );
        callback();
      }
    }
  }( times, 0 );

  window.setTimeout( internalCallback, factor );
};

// console.log() requires firebug    
setDeceleratingTimeout( function(){ console.log( 'hi' );}, 10, 10 );
setDeceleratingTimeout( function(){ console.log( 'bye' );}, 100, 10 );
Peter Bailey
By callback, do you mean the last line of the function calls itself recursively with a setTimeout(..., newInterval) ?
Marc
I assume that is what he meant. I just tried that and it seems to be working. Thanks, guys!
joeydi
@joeydi, agreed. I just wanted to state it in case others dont! ;)
Marc
Added an example of a re-usable callable
Peter Bailey
+1  A: 

I like this question - inspired a little timer object in me:

window.setVariableInterval = function(callbackFunc, timing) {
  var variableInterval = {
    interval: timing,
    callback: callbackFunc,
    stopped: false,
    runLoop: function() {
      if (variableInterval.stopped) return;
      var result = variableInterval.callback.call(variableInterval);
      if (typeof result == 'number')
      {
        if (result === 0) return;
        variableInterval.interval = result;
      }
      variableInterval.loop();
    },
    stop: function() {
      this.stopped = true;
      window.clearTimeout(this.timeout);
    },
    start: function() {
      this.stopped = false;
      return this.loop();
    },
    loop: function() {
      this.timeout = window.setTimeout(this.runLoop, this.interval);
      return this;
    }
  };

  return variableInterval.start();
};

Example use

var vi = setVariableInterval(function() {
  // this is the variableInterval - so we can change/get the interval here:
  var interval = this.interval;

  // print it for the hell of it
  console.log(interval);

  // we can stop ourselves.
  if (interval>4000) this.stop();

  // we could return a new interval after doing something
  return interval + 100;
}, 100);  

// we can change the interval down here too
setTimeout(function() {
  vi.interval = 3500;
}, 1000);

// or tell it to start back up in a minute
setTimeout(function() {
  vi.interval = 100;
  vi.start();
}, 60000);
gnarf
Thanks - set me off in the right direction for something similar I'm working on.
Colonel Sponsz