1

I have a function set up like this

awesomeFirePenguin: function(){
   // function does some stuff, not important
},

and I call it in a for loop like this

for (var i = 0; i < n; i++){
   this.awesomeFirePenguin();           
}

This works, the function is called n times, but the results of the function are shown immediately after each other. What I want is for the results to be shown after each other with a slight delay, like 100ms or so. Something klike this

for (var i = 0; i < n; i++){
   this.awesomeFirePenguin(); 
   // wait a while and then continue    
}

I tried using

for (var i = 0; i < n; i++){
    window.setTimeout(this.awesomeFirePenguin(), 100);
}

and window.setInterval(this.awesomeFirePenguin(), 100);, but both only execute the function once.

finrod
  • 72
  • 1
  • 9
  • The unique thing about my problem is the way I have my function set up and I can't change that. If I use the solutions in the other question, I end up with what I describe at the end of my question. – finrod Jul 24 '13 at 18:06

2 Answers2

3

setTimeout and setInterval can take functions as arguments, but what you were doing is calling them. Thus, they were receiving not the function, but its return value as an argument.

If you want to delays to stack, you can just multiple the timeout delay by whatever loop index you're currently at.

for (var i = 0; i < n; i++){
    window.setTimeout(this.awesomeFirePenguin.bind(this), 100 * i);
}
voithos
  • 68,482
  • 12
  • 101
  • 116
  • Might be necessary to wrap the function or use `.bind()` to preserve the context (`this`) – Pointy Jul 24 '13 at 18:05
  • @finrod: No prob, and welcome to StackOverflow! If you haven't already, check out the quick [tour](http://stackoverflow.com/about). – voithos Jul 24 '13 at 18:19
2

The answer by voithos is probably the simplest. You can also use an asynchronous execution library like Clumpy.js, where you could write your code as:

var clumpy = new Clumpy({delay: 100});
var i;
clumpy.for_loop(
    function() { i = 0; },
    function() { return i < n; },
    function() { ++i; },
    this.awesomeFirePenguin
);

It's also possible to do this using a closure and a self-invoking function, but it's ugly code that's hard to understand:

(function loop(i, f) {
   setTimeout(function () {
      f();
      if (--i) loop(i, f);
   }, 100)
}(n, this.awesomeFirePenguin));

It's possible to write something using setInterval instead of setTimeout, but it's not any easier to comprehend, although it probably eliminates the recursive calls.

Community
  • 1
  • 1
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521