2

I want to pause 1 second for every time it loops, it is usually easy to do similar pauses on other cases, but when working with loops, it seems it get harder:

for (var i=0 ; i < 10 ; i++) {
    document.write (i + "<br>");
    // I want to wait 1 second here
}

This is one example of my thousands failed attempts:

function writeMsg (index) {
    document.write (index + "<br>");
}

for (var i=0 ; i < 10 ; i++) {
    setTimeout (writeMsg(i), 1000);
}

Any ideas of how to get this to work?

ajax333221
  • 11,436
  • 16
  • 61
  • 95
  • 3
    possible duplicate of [setTimeout in a for-loop and pass i as value](http://stackoverflow.com/questions/5226285/settimeout-in-a-for-loop-and-pass-i-as-value) and http://stackoverflow.com/questions/6564814/passing-argument-to-settimeout-in-a-for-loop and http://stackoverflow.com/questions/5986588/calling-settimeout-function-within-a-loop and http://stackoverflow.com/questions/6425062/passing-functions-to-settimeout-in-a-loop-always-the-last-value and http://stackoverflow.com/questions/3445855/javascript-how-to-pass-different-object-to-settimeout-handlers-created-in-a-loo and about 100k others – Matt Ball Mar 26 '12 at 21:51
  • Actually his main problem is the fact that he calls `writeMsg(i)` immediately instead of passing a function to setTimeout... – ThiefMaster Mar 26 '12 at 21:56
  • 2
    @MДΓΓБДLL suprisingly though not a lot of those get proper answers :s... – sg3s Mar 26 '12 at 22:24

5 Answers5

9

This function works more like a normal for loop while it isn't

You need to take into account that a for gets 3 arguments inbetween semicolons.

  1. Before starting (ie var i=0 you define a variable)
  2. A condition before running the code again (ie i < 10 while i is under 10)
  3. An action everytime it finishes the code again (i++ add one to i)

Code

(function() {
    // Define a variable
    var i = 0,
        action = function() {
            // Condition to run again
            if (i < 10) {
                document.write(i + "<br>");

                // Add one to i
                i++;
                setTimeout(action, 1000);
            }
        };

    setTimeout(action, 1000);
})();

Here is a jsfiddle for this code demonstrating its working: http://jsfiddle.net/sg3s/n9BNQ/

sg3s
  • 9,411
  • 3
  • 36
  • 52
  • My code can be simplified by just wrapping that if arround the new setTimeout instead of the whole function, I guess. – sg3s Mar 26 '12 at 22:11
4

You pass the return value of a function call to setTimeout instead of a function. Try the following code:

for (var i = 0; i < 10; i++) {
    (function(i) {
        setTimeout(function() {
            writeMsg(i);
        }, 1000*i);
    })(i);
}

In case you wonder why the call is wrapped inside an anonymous function: Without that function each setTimeout callback would receive the same i so when the callbacks fire it would always be 10. The anonymous function creates a new i inside that is not connected to the loop variable.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • they get printed all at the same time (Chrome) – ajax333221 Mar 26 '12 at 21:45
  • Yeah, i forgot `1000*i` instead of just `1000`. You probably copied the initial version. – ThiefMaster Mar 26 '12 at 21:45
  • it prints `10` every time. But I can make it work with some modifications – ajax333221 Mar 26 '12 at 21:47
  • try now. mixed up the two functions – ThiefMaster Mar 26 '12 at 21:47
  • just a question, why do you multiply by `i`?, On my real code I start index `i=37` and start `i--`, will it fail then? – ajax333221 Mar 26 '12 at 21:51
  • The timeouts are started at the same time. So in each iteration you need one second more. If `i` doesn't start with zero, add a second variable that is increased in every loop and starts with zero: `for(var i = whatever, j = 0; i < 10; i++, j++)` and use `1000*j` – ThiefMaster Mar 26 '12 at 21:52
  • 1
    This just starts up x amounts of timeouts, while this works for small numbers it will be hell if you try to start too many. This also disregards the possibility to break of the for loop mid-way by setting i higher than 10. This is in my opinion a really horrible way to do this. – sg3s Mar 26 '12 at 22:01
1

Classic function-in-a-loop problem. One archetypal solution:

function createCallback(i) {
    return function () {
        writeMsg(i);
    };
}

function writeMsg (index) {
    document.write (index + "<br>");
}

for (var i=0 ; i < 10 ; i++) {
    setTimeout (createCallback(i), 1000*i);
}
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • D'oh, bungled the parens. That's why I like the separate callback generator anyway - easier to write, easier to read. – Matt Ball Mar 26 '12 at 21:46
  • Bad way to do it, you start up multiple timeouts and break normal for functionality because you cannot otherwise change i to affect the other potential loops of the code. – sg3s Mar 26 '12 at 22:08
  • @sg3s I beg your pardon? Your comment is unclear. I can't say that I've ever heard of scheduling `O(10)` timeouts causing problems. – Matt Ball Mar 26 '12 at 23:52
  • It is bad practice. The OP didn't just want to write a message to the document but obviously preform several or the same action time after time again. Doing it this way wont allow you to intervene after you've started all the timeouts, being the beginning, while he might decide at loop #5 that it has been enough, for w/e reason, and then set i to 10... He asks for a for loop wich is delayed each loop. Not a way to fire function x y number of times with a different variable, no way of stopping what they will do. – sg3s Mar 27 '12 at 06:05
1

The 10 timeouts are all based on the time that setTimeout() is called. So, they are all triggered at the same time.

for (var i=0; i < 10; i++) {
    (function(idx){
        setTimeout(function(){
            document.write(idx+"<br/>");
        },1000*idx);
    })(i);
};
Maz
  • 3,375
  • 1
  • 22
  • 27
  • Bad way to do it, you start up multiple timeouts and break normal for functionality because you cannot otherwise change i to affect the other potential loops of the code. – sg3s Mar 26 '12 at 22:06
0

try this it will definitely help who all are think how to make it work wait property inside For Loop... try this code in this URL http://www.shopjustice.com/the-collections/C-10329.

var var2;
var tmp;
var evt;
var i=0;
var res = document.getElementsByClassName('mar-plp-filter-content nav nav--stacked')[0].children.length;
tmp = document.getElementsByClassName('mar-plp-filter-content nav nav--stacked')[0].children;
function myfunc()
{
if(i<res)
{
var2 = tmp[i].getElementsByTagName("span")[0].getElementsByClassName("inverted")[0];
// alert(var2.innerHTML);
var evObj = document.createEvent('MouseEvents');
evObj.initEvent( 'mouseover', true, false );
var2.dispatchEvent(evObj);
var2.style.backgroundColor="GREEN";
i++;
setTimeout(myfunc,3000);
}
};
setTimeout(myfunc,3000);