1

i'm writing a code and i've stuck with setTimeout function. I would like to get animation effect. Display elements of array with delay. Code is done.

for (var i=0;i <= array.length-1;i++) {
                        (function(el) {
                            setTimeout(function(){
                             document.getElementById('Result').innerHTML += Math.floor(el);
                             console.log(Math.floor(el));
                            }, 3000*(i+1));
                        })(array[i]);

I had problem with delay when i use for (var i=array.length-1; i>=0;i--) Why? (The idea of this code is display items array form the last to the first)

for (var i=0;i <= array.length-1;i++) {
                        (function(el) {
                            setTimeout(function(){

Give now the same resultat as: for (var i=array.length-1; i>=0;i--) { console.log(array[i]+'!')

  • Any particular reason why you aren't using [jQuery](http://jquery.com/)? It makes this sort of thing is *really* trivial. – James Jul 29 '14 at 22:03
  • In your `setTimeout` code snippet you didn't put in a delay time: `}(array,i), 3000);` – jwatts1980 Jul 29 '14 at 22:06
  • You are calling the function immediately and pass the return value `undefined` to `setTimeout`. – Felix Kling Jul 29 '14 at 22:06
  • jQuery has nothing to do with this; it's just not written correctly. you do need an anon in the loop to capture i and array, but that anon needs to be invoked immediately. instead, you are invoking the setTimeout callback immediately. – dandavis Jul 29 '14 at 22:07
  • *"YOU ANSVERS DONT WORK! Uncaught SyntaxError: Unexpected token ( "* I think syntax errors are the easiest thing to fix. Read these articles to [learn](http://juliepagano.com/blog/2014/05/18/javascript-debugging-for-beginners) [how to](http://www.creativebloq.com/javascript/javascript-debugging-beginners-3122820) [**debug** JavaScript](https://developers.google.com/chrome-developer-tools/docs/javascript-debugging), so you can help yourself. – Felix Kling Jul 30 '14 at 02:18

3 Answers3

8

The problem here is about closures. A closure is a type of anonymous function used to remember the arguments for using them later in asynchronous code (e.g. in functions called by setTimeout).

If you write something like:

setTimeout(function(foo){...}(value), 3000)

the function gets called before calling setTimeout. You have to use a closure to do this:

(function(foo){ 
    setTimeout(function() { 
        ... do something with foo ... 
    }, 3000);
})(value_of_foo);

This code will remember the value of foo creating a setTimeout with a function that uses it.

Another problem is that you have to increase the setTimeout time to create a delay, otherwise the for will create a bunch of setTimeout(..., 3000) that will be executed all at once. So what you will need to do to your code is something like the following:

for (var i = 0; i <= array.length; i++) {
    (function(el) {
        setTimeout(function(){
            document.getElementById('Result').innerHTML += Math.floor(el)
        }, 3000 * i);
    })(array[i]); 
}
Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
1

Timeouts don't execute until after your main function has finished, this means that by the time your timeout function executes per loop, your i variable will be at its final value (in this case = 0). Your function declaration is also incorrect as the timeout function does not pass in those parameters for you. To do this, you need to wrap your timeout inside of another function call that takes in the parameters for the current loop, try something like this instead...

for (var i=array.length-1; i>=0;i--) {
  function(array, i) {
    setTimeout(function() {
      document.getElementById('Result').innerHTML += Math.floor(array[i]);
    }, (i+1) * 3000);
  }(array, i);
}
Lochemage
  • 3,974
  • 11
  • 11
0

First of all you are immediately calling the function and its result is assigned as the callback of the timeout. (this is wrong as the first argument must be a function)

Then, you have some syntax errors with missing closing } and )..

Try

for (var i=array.length-1; i>=0;i--) {
    function(array,i){ 
        setTimeout(function(){
            document.getElementById('Result').innerHTML += Math.floor(array[i]);
        }, 3000*i);
    }(array,i);
}

I used 3000*i so that each timeout is 3 seconds after the other

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317