0

I'm trying to create a loop with a setTimeout in console log browser. But it is not working. I tried searching but have not found what I needed. Basically in each loop would be 5sec intervals during this printa 5sec in late updates. Would have to bring an array into the loop.

var myArray1 = new Array( "orange", "blue", "white" );

for (var i = 0; i <= myArray1.length; i++) {

  console.log("This fruit" + myArray1[i] + "is delcious!");

  setTimeout(function(){ alert() }, 500); //AFTER FIVE SECONDS

setTimeout(function(){
  } //CLOSE FOR
}, 5000); //AFTER FIVE SECONDS

Let me give an example that I used and it works, but the code is too large. I wanted a way to better understand loop.

var myArray1 = new Array( "orange", "blue", "white" );
var var_time = 7000;

setTimeout(function(){
  console.log("Fruit is " + myArray1[0]);
  console.log("...stage 1 loading");


  setTimeout(function(){
    console.log("Fruit is " + myArray1[1]);
    console.log( "...stage 2 loading");

    setTimeout(function(){
      console.log("Fruit is " + myArray1[2]);
      console.log( "stage 2 finish");

      alert();

      console.log( "You code run perfect");

    }, var_time); //stage 2
  }, var_time); //stage 1
}, 500); //stage 0
michel
  • 62
  • 8
  • 1
    use `5000 * i` for your timeout inside of the for loop. remember, javascript is asynchronous, so all of the setTimeouts will run at essentially the same time. – r3wt Jan 14 '15 at 16:15
  • 3
    See: http://stackoverflow.com/questions/26380086/how-browser-execute-javascript-render-asynchronous/26381899#26381899 – KooiInc Jan 14 '15 at 16:16

2 Answers2

1

Not pretty, but simple.

var fruitColors = ["orange", "blue", "white"];

function showColor(index) {
   if (index < fruitColors.length) {
       console.log("Fruit is " + fruitColors[index]);
       setTimeout(function() { showColor(index+1); }, 500);
   }
}

setTimeout(function() { showColor(0); }, 500);

A prettier but more complicated way would be:

var fruitColors = ["orange", "blue", "white"];

fruitColors.reverse().reduce(function(m,c) {
    return function() {
       console.log("Fruit is " + c);
       setTimeout(m, 500);
    };
}, function() {})();

You can read about reduce here (MDN).

dusky
  • 1,003
  • 7
  • 12
  • This code violates the "Don't Repeat Yourself" principle – Alnitak Jan 14 '15 at 17:19
  • @Alnitak yes, but I think it's easier to understand. – dusky Jan 14 '15 at 17:34
  • The code he did was modify and use for what I wanted. Wanted to make clear that you guys helped a lot. But luckily for what I need this code already served me. Thanks. @Alnitak Not get hurt. – michel Jan 14 '15 at 17:45
0

My usual code for this would be:

var myArray1 = [ "orange", "blue", "white" ];

(function loop() {
    // find first element and do something with it
    var current = myArray1.shift();
    ...

    if (myArray1.length) {
        setTimeout(loop, 5000);
    }
})();  // start immediately

This does of course mutate the array as the loop runs - take a copy if that's a problem.

A more general version is this:

function repeat(array, delay, callback, done) {
    var a = array.slice();
    (function loop() {
        var x = a.shift();
        callback(x);
        if (a.length) {
            setTimeout(loop, delay);
        } else {
            done();
        }
     })();
};

with usage:

repeat(myArray1, 5000, function(f) {
    console.log(f)
}, function() {
    console.log(done);
}
Alnitak
  • 313,276
  • 69
  • 379
  • 466
  • Why not `setInterval()`? – Ismael Miguel Jan 14 '15 at 17:09
  • When I put `console.log("This fruit " + myArray1 + " is delcious!");` he is putting twice and repeats four times and not three – michel Jan 14 '15 at 17:11
  • you should be logging "current", not the whole of `MyArray1` – Alnitak Jan 14 '15 at 17:12
  • 2
    @IsmaelMiguel: Both are good options, but I think it is better to use `setTimeout` over `setInterval` here. Because we have a simple termination condition, you can stop the repeated calls with the simple `if (current.length) {…}` wrapper around the next call instead of having to [keep track of a timer ID](http://stackoverflow.com/questions/1831152/how-to-stop-setinterval). – markegli Jan 14 '15 at 17:17
  • @IsmaelMiguel what markegli said. Also, `setInterval` behaves badly if timer intervals are missed. – Alnitak Jan 14 '15 at 17:19
  • @michel I made a typo - the `current.length` should of course have read `myArray1.length` !! – Alnitak Jan 14 '15 at 17:20
  • Actually, the `setInterval` will force it's execution as soon as possible. Imagine you have 5 tasks in queue, and `setInterval` is the 4th. `setInterval` will execute as soon as the time interval has past, skipping all the other 3 tasks ahead – Ismael Miguel Jan 14 '15 at 17:24
  • @IsmaelMiguel no, it never skips the tasks, but if the execution time is missed it'll run all the tasks as quickly as possible. A "self-triggered" `setTimeout` loop on the other hand cannot do this - there will always be _at least_ the specified delay between tasks. – Alnitak Jan 14 '15 at 17:26
  • Your `console.log` line is supposed to replace the `...` !! – Alnitak Jan 14 '15 at 17:28