Weird infinite loop bug in jquery recursive function
I have a strange issue on the project I'm working with. This changes an image source and a content of a div automatically.
I have coded a function, but it falls into infinite loop and page does not load (page is showing the loading page always).
These are the codes:
$.fn.extend({
changehaber: function(a){
$('#cokokunanlarcontent').fadeOut('slow',function() {
$('.jquerycokokunanlarbutton').attr('src','images/sabah/buton-pasif.png');
$('img[rel="'+a+'"]').attr('src','images/sabah/buton-aktif.png');
}).html($('#'+a).html()).fadeIn('slow');
return this;
}
});
function slidecokokunanlar() {
$('#cokokunanlarcontent').html($('#cokokunanlar1').html()).delay(3000).changehaber('cokokunanlar2').delay(3000).c开发者_如何学JAVAhangehaber('cokokunanlar3').delay(3000).changehaber('cokokunanlar4').delay(3000).changehaber('cokokunanlar5').delay(3000);
slidecokokunanlar();
}
slidecokokunanlar();
What's the issue here, when this is executed, I want the function to work infinitely, but the page shows it's always loading. This is the console's output:
Uncaught RangeError: Maximum call stack size exceeded
Thanks in advance
You can't call a function from inside itself without blocking up the whole execution stack. By calling the function from inside itself, you're effectively preventing it from ever returning, and as Javascript is single-threaded, everything will grind to a halt!
Change your function to this:
function slidecokokunanlar() {
$('#cokokunanlarcontent').html($('#cokokunanlar1').html()).delay(3000)...
setTimeout(slidecokokunanlar, 0);
}
This allows for concurrent execution without blocking the UI, thus allowing your page to remain responsive.
See this article on "chunking" for more information on how this works.
This is because JavaScript doesn't have proper tail calls.
Your function calls itself at the end of itself forever. The first one never finishes and returns, nor does the second, nor do any of them until you run out of stack and explode.
You might try using setTimeout
instead. See an example on jsFiddle.
EDIT You might not want to use 0 unless you really need it to be running continuously. Even using 100, you'd execute the function 10 times per second.
function foo(){
console.log('foo');
setTimeout(foo, 0);
}
foo();
Here's a cleaner way to do it.
var coko = $('#cokokunanlarcontent'); // cokokunanlarcontent
var cokos = $('[id^="cokokunanlar"]').not(coko); // cokokunanlar1..2..3 etc
var total = cokos.length; // total quantity
var i = 0;
var allow = true;
$('.jquerycokokunanlarbutton').attr('src','images/sabah/buton-pasif.png');
function slidecokokunanlar( isRestart ) {
if( !isRestart ) {
$('img[rel="' + cokos[i].id + '"]').attr('src','images/sabah/buton-aktif.png');
coko.html( cokos.eq(i).html() )
.fadeIn( 'slow' );
}
if( allow ) {
coko.delay( 3000 )
.fadeOut('slow', function() {
i = (++i % total);
slidecokokunanlar(); // recursively call with next index or 0
});
}
}
slidecokokunanlar(); // start it off
function restartSlider() {
allow = true;
slidecokokunanlar( true );
}
function stopSlider() {
allow = false;
}
stopSlider(); // to stop it
restartSlider(); // to restart it
精彩评论