38
function slide()
{
    if($('.current').is(':last-child')){
        $('.current').removeClass('.current');
        $('#imgholder').first().addClass('.current');
        $('#imgholder').animate({left: '3920px'});
    }
    else{
        $nxt=$(".current");
        $(".current").removeClass("current");
        $nxt.next().addClass("current");
        $('#imgholder').animate({left: '-=980'},{duration: 'slow', easing: 'easeOutBounce' });
        }
}
var loop_handle= setTimeout("slide()",'3000');

I have put this code in header section and the setTimeout runs only once.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
pahnin
  • 5,367
  • 12
  • 40
  • 57

8 Answers8

99

setTimeout should only run once. You're looking for setInterval.

var loop_handle = setInterval(slide, 3000);

Also, the second argument should be a number, not a string. When the function call doesn't require any arguments, it's better to reference to the function instead of using a string. A string would be converted to a function. This function will be executed within the scope of the window.

  setInterval("slide()", 3000);
//becomes
  setInterval(Function("slide();"), 3000);
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Rob W
  • 341,306
  • 83
  • 791
  • 678
8

Yes, setTimeout only runs once. You want setInterval. This function also returns an ID you can use to cancel the interval. For example:

const slideInterval = setInterval(slide, 3000);

// later...
clearInterval(slideInterval);
uɥƃnɐʌuop
  • 14,022
  • 5
  • 58
  • 61
5

You are looking for setInterval

See: https://developer.mozilla.org/en/window.setInterval

AndreyKo
  • 901
  • 7
  • 16
5

The setTimeout function only runs once! If you want to run it in more times you should use setInterval:

var loop_handle= setInterval("slide()",'3000');

Also you can use setTimeout in the end of the slide() function to re-set-timeout again:

var loop_handle;
function slide() {
    if($('.current').is(':last-child')) {
        $('.current').removeClass('.current');
        $('#imgholder').first().addClass('.current');
        $('#imgholder').animate({left: '3920px'});
    }
    else {
        $nxt=$(".current");
        $(".current").removeClass("current");
        $nxt.next().addClass("current");
        $('#imgholder').animate({left: '-=980'},{duration: 'slow', easing: 'easeOutBounce' });
    }
    loop_handle = setTimeout("slide()",'3000');
}
loop_handle = setTimeout("slide()",'3000');
amiry jd
  • 27,021
  • 30
  • 116
  • 215
  • 1
    Cool. but you can do this for a bit better performance : var selector = $('#imgholder'); selector.dowhatever – Shahin Oct 24 '11 at 09:27
4

use setTimeout with recursion (endless loop)

If you want to keep the exact space between each function call use setTimeout instead setInterval. setInterval can overlap at some point and this is often not expected behavior. This way you can also and couter and stopit if xondi

(function test(){
  setTimeout(function(){
    console.log(1);
    test();
  }, 2000)
})()

Or use it with conditions;

// Declare recursive function
function test(runCount, runMax, waitBeforeRun){
  // ... do sometnig here
  console.log("runCount " + runCount);
  console.log("waitBeforeRun " + waitBeforeRun);

  // adjust your varibles in loop
  runCount++;
  let reduceWaitRunTimeBy = 99;
  waitBeforeRun = 0 > waitBeforeRun - reduceWaitRunTimeBy ? waitBeforeRun : waitBeforeRun -= reduceWaitRunTimeBy;
   
 /** Run recursion 
  *  if "if" condition will not make a return
  **/
  if(runCount > runMax) return;
     
  setTimeout(test.bind(null, runCount, runMax, waitBeforeRun), waitBeforeRun);
  
}

// Run Timeout
let runCount = 0;
let runMax = 30;
let waitBeforeRun = 2000;
setTimeout(test.bind(null, runCount, runMax, waitBeforeRun), waitBeforeRun);

Try it with my Code Pen here

Which would output in your console this:

"runCount 0"
"waitBeforeRun 2000"
"runCount 1"
"waitBeforeRun 1901"
"runCount 2"
"waitBeforeRun 1802"
"runCount 3"
"waitBeforeRun 1703"
"runCount 4"
"waitBeforeRun 1604"
"runCount 5"
"waitBeforeRun 1505"
"runCount 6"
"waitBeforeRun 1406"
"runCount 7"
"waitBeforeRun 1307"
"runCount 8"
"waitBeforeRun 1208"
"runCount 9"
"waitBeforeRun 1109"
"runCount 10"
"waitBeforeRun 1010"
"runCount 11"
"waitBeforeRun 911"
"runCount 12"
"waitBeforeRun 812"
"runCount 13"
"waitBeforeRun 713"
"runCount 14"
"waitBeforeRun 614"
"runCount 15"
"waitBeforeRun 515"
"runCount 16"
"waitBeforeRun 416"
"runCount 17"
"waitBeforeRun 317"
"runCount 18"
"waitBeforeRun 218"
"runCount 19"
"waitBeforeRun 119"
"runCount 20"
"waitBeforeRun 20"
"runCount 21"
"waitBeforeRun 20"
"runCount 22"
"waitBeforeRun 20"
"runCount 23"
"waitBeforeRun 20"
"runCount 24"
"waitBeforeRun 20"
"runCount 25"
"waitBeforeRun 20"
"runCount 26"
"waitBeforeRun 20"
"runCount 27"
"waitBeforeRun 20"
"runCount 28"
"waitBeforeRun 20"
"runCount 29"
"waitBeforeRun 20"
"runCount 30"
"waitBeforeRun 20"

Or use OOP - Code Pen here

DevWL
  • 17,345
  • 6
  • 90
  • 86
4

You only call it once, so it'll only execute once.

Perhaps you're thinking of "setInterval()".

When you call it, by the way, just pass the name of the function and not a string:

setInterval(slide, 3000);
Pointy
  • 405,095
  • 59
  • 585
  • 614
2

That's because setTimeout() is supposed to run only once. In order to fire an event on set intervals user setInterval().

MeLight
  • 5,454
  • 4
  • 43
  • 67
0

This problem usually happens when you used setTimeout in recursion loop, for example in ajax callback and when you want to run something out of recursion, you expect setTimeout to work as past. remember to use setInterval in non-recursion functions.

Cyber
  • 9
  • 1
  • 2