1

I'm trying to make a slideshow using Jquery, the pictures are cycled by a function that calls itself every 5.5 seconds. However, I'm trying to avoid recursion since it is very expensive comparing to iterative calls. And I'm assuming that is the cause for IE to have a non-stopping loading icon when my slideshow is loaded. So I want to convert the following function to an iterative one.

function playslides()
{

//hide previous slide
$(document.getElementById(t)).fadeOut("slow");


//reset slide index
calcSildes();

//show new slide
$(document.getElementById(t)).fadeIn("slow");

//recursive call after 5.5 sec
timer = setTimeout("playslides()", 5500);

}


//on page load...

$(document).ready(

playslides();

);

so far my two approaches are:

  1. create a while loop inside the $(document).ready() function and loop playslides() function.

  2. create another timer function that calls the playslides() function, and let playslides function call that timer function. (Not sure if this avoids recursion at all...)

Thanks!!

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
eastboundr
  • 1,857
  • 8
  • 28
  • 46
  • 1
    Why not use one of the many jquery slide show plugins? – jrummell Jan 05 '12 at 18:46
  • Why do you think it is terribly expensive? Your repeated DOM selection will be the most expensive thing that should be fixed. –  Jan 05 '12 at 19:11
  • Thanks all, after I changed the function to use SetInterval instead of SetTimeout, the spinning loading icon of IE still persists after page load, any ideas what might caused this? Could it be the "repeated DOM selection"? Thanks! – eastboundr Jan 05 '12 at 21:10

4 Answers4

5

Sounds like you should replace setTimeout() with setInterval(), which will simply repeat the given function until its canceled. No recursion or looping necessary.

Quoting John Resig, creator of jQuery:

At a fundamental level it's important to understand how JavaScript timers work. Often times they behave unintuitively because of the single thread which they are in. Let's start by examining the three functions to which we have access that can construct and manipulate timers.

var id = setTimeout(fn, delay); - Initiates a single timer which will call the specified function after the delay. The function returns a unique ID with which the timer can be canceled at a later time.

var id = setInterval(fn, delay); - Similar to setTimeout but continually calls the function (with a delay every time) until it is canceled.

clearInterval(id);, clearTimeout(id); - Accepts a timer ID (returned by either of the aforementioned functions) and stops the timer callback from occurring.

Using setInterval, you could simplify your code to the following:

function playslides()
{
    //hide previous slide
    $(document.getElementById(t)).fadeOut("slow");

    //reset slide index
    calcSildes();

    //show new slide
    $(document.getElementById(t)).fadeIn("slow");
}

$(document).ready(function() {
     setInterval(playslides, 5500);
});
jrummell
  • 42,637
  • 17
  • 112
  • 171
  • 2
    It is worth reading through the answer by bobince to this post: http://stackoverflow.com/questions/729921/settimeout-or-setinterval - A great reasoning about the differences between when to use `setTimeout` and when to use `setInterval`. – Christofer Eliasson Jan 05 '12 at 19:24
  • Thanks jrummell, but after I changed the function to use SetInterval instead of SetTimeout, the spinning loading icon of IE still persists after page load, any ideas what might caused this? Thanks! – eastboundr Jan 05 '12 at 21:11
  • That usually means a resource (image, script, etc) is still loading. I don't see anything in your code sample that would cause that. – jrummell Jan 05 '12 at 21:19
2

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

var intervalID = window.setInterval(playslides, 5500);
jbabey
  • 45,965
  • 12
  • 71
  • 94
1

You can't create a loop with delayed iterations.

The only optimization is replacing "playslides()" with playslides, and caching the jQuery objects which refer to the same object:

var timer;
function playslides($element) {
    //hide previous slide
    $element.fadeOut("slow");

    //reset slide index
    calcSildes();

    //show new slide
    $element.fadeIn("slow");

    //recursive call after 5.5 sec
    timer = setTimeout(playslides, 5500, $element);
}

// Bug fix too, wrap document.ready in `function(){
$(document).ready(function(){
    playslides($("#"+t));    
});
Rob W
  • 341,306
  • 83
  • 791
  • 678
1

This is not a recursive function. A recursive function continues to create and retain copies of itself in memory until the base case is reached, after which, the stack unwinds and values are returned. There must also be a change to the parameters in the recursive call which will eventually lead to the base case.

PHP Example:

function recursive_function($num){
    if ($num == 0){ //base case
        return 10;
    }else{
        return $num + recursive_function($num-1);
    }
}

recursive_function(5);//output is 25

Your function is just creating new timers which call the same function after the original has left memory.

Remove the 'timer = setTimeout(playslides, 5500, $element);' line in the playslides function.

Replace the 'playslides($("#"+t));' call in the document.ready function with:

timer = window.setInterval(function(){
    playslides($("#"+t));
}, 5500);

You need to create an anonymous function for setinterval to properly pass parameters (for older browsers...not in HTML5).

elchivo1250
  • 106
  • 1
  • 1