4

I'm trying to write a simple loop in JS (or JQuery) that updates an image every five seconds, for a total of 15 seconds (so three loops), and then quits.

It should go like this:

  1. Wait five seconds
  2. Execute
  3. Wait five seconds
  4. Execute
  5. Wait five seconds
  6. Execute
  7. Quit

But setTimeout only seems to work once.

As a test, I've tried:

function doSetTimeout(i) {
  setTimeout(function() { alert(i); }, 5000);
}

for (var i = 1; i <= 5; ++i)
  doSetTimeout(i);

Does not work: http://jsfiddle.net/ubruksco/

I've also tried:

for(var i = 1; i <= 5; i++) {
    (function(index) {
        setTimeout(function() { alert(index); }, 5000);
    })(i);
}

Does not work: http://jsfiddle.net/Ljr9fq88/

Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
  • 1
    You are looking for `setInterval(function(){...}, 5000);` https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval You can store that interval in a variable and clear it after a certain condition is met... in your case after the 5th iteration – Joe Feb 24 '15 at 14:06
  • `var i = 1; i <= 5; i++` will never do three loops – KyleK Feb 24 '15 at 14:11
  • @KyleK It also won't change an image. As I stated, these were just test loops. – Chuck Le Butt Feb 24 '15 at 14:17

8 Answers8

27
var time = 1;

var interval = setInterval(function() { 
   if (time <= 3) { 
      alert(time);
      time++;
   }
   else { 
      clearInterval(interval);
   }
}, 5000);

you can simply create an interval and kill it after the 3rd time

astian
  • 684
  • 7
  • 18
6

Your first example is nearly there. You just need to multiply the time delay by the loop index to get the right delay.

function doSetTimeout(i) {
  setTimeout(function() { alert(i); }, 5000*i);
}

for (var i = 1; i <= 3; ++i)
  doSetTimeout(i);

http://jsfiddle.net/ubruksco/3/

4

The reason is that your settimeout ends all at the same time (after 5 seconds) because your timeout code is based on 5 seconds

for(var i = 1; i <= 5; i++) {
    (function(index) {
        setTimeout(function() { alert(index); }, 5000);
    })(i);
}

What you want to do is change the timeout time based on your index (hence will have different start times.

for(var i = 0; i < 3; i++) {
    (function(index) {
        setTimeout(function() { alert(index); }, index*5000);
    })(i);
}

(Also needs 3 iterations, so edited out the loop for you)

Secret
  • 3,291
  • 3
  • 32
  • 50
  • @Chuck please note that setting multiple timers at once is a bad practice. You should set a timer in a recursive function. – Karl-André Gagnon Feb 24 '15 at 14:37
  • @Karl-AndréGagnon I guess I could `clearTimeout` the three? Or after each loop? – Chuck Le Butt Feb 24 '15 at 15:45
  • 1
    @Chuck No no no, it's not about the clear timeout, it is about having 3 timers running at the same time. One that last 500ms, one at 1000ms and one at 1500ms. You should wait until 1 timer finish before triggering the other one, just like that : http://jsfiddle.net/tsx18ttf/ – Karl-André Gagnon Feb 24 '15 at 15:55
  • @Karl-AndréGagnon Ah yes, I see your point now. That makes most sense, and is indeed the answer I was looking for. Thanks! – Chuck Le Butt Feb 24 '15 at 15:57
2

You want setInterval() instead

 setInterval(function(){ alert("Do Something"); }, 3000);
User970008
  • 1,135
  • 3
  • 20
  • 49
2

Make it easy! You do not need loop, you just need three executions.

setTimeout(function() { alert(1); }, 5000);
setTimeout(function() { alert(2); }, 10000);
setTimeout(function() { alert(3); }, 15000);

But, if you really want a loop:

function doSetTimeout(i) {
    setTimeout(function() { alert(i); }, i*5000);
}
for (var i = 1; i <= 3; ++i)
    doSetTimeout(i);
Filipe Borges
  • 2,712
  • 20
  • 32
1

Assuming your are using jQuery (to manipulate the DOM),

you can try this:

['img1.jpg', 'img2.jpg', 'img3.jpg'].forEach(function(imgPath, index) {
    // the callback will be executed in 5seconds * (index + 1)
    setTimeout(function() {
       // change image source
       $('img#myImage').attr('src', imgPath);
    }, 5000 * (index + 1));
});
Eloims
  • 5,106
  • 4
  • 25
  • 41
1

With setTimeout:

function doSetTimeout(i) {
    if(i >= 3) return;
    alert(i);
    setTimeout((function () {
        return function () {
            doSetTimeout(i);
        };
    })(i + 1), 5000);
}

doSetTimeout(0);

But you can also use setInterval, maybe more appropriate.

KyleK
  • 4,643
  • 17
  • 33
1

You can use setInterval instead and track how much times you have executed function. Than just use clearInterval() to stop execution.

var i = 1;
var interval = setInterval(function() {
  execute();
}, 5000);

$(document).ready(function() {
  execute();
});

function execute() {
  $("#output").append("set<br/>");

  if (i == 3) {
    clearInterval(interval);
  }
  i++;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='output'></div>

If you want to first wait 5 secs, don't call execute() on domready.

Justinas
  • 41,402
  • 5
  • 66
  • 96