jquery递归函数中奇怪的无限循环错误

时间:2011-06-28 14:21:23

标签: javascript jquery loops

我在与我合作的项目上有一个奇怪的问题。这会自动更改图像源和div的内容。

我编写了一个函数,但是它进入无限循环并且页面没有加载(页面总是显示加载页面)。

这些是代码:

$.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).changehaber('cokokunanlar3').delay(3000).changehaber('cokokunanlar4').delay(3000).changehaber('cokokunanlar5').delay(3000);
    slidecokokunanlar();
}

slidecokokunanlar();

这里有什么问题,当执行此操作时,我希望函数无限工作,但页面显示它始终在加载。这是控制台的输出:

Uncaught RangeError: Maximum call stack size exceeded

提前致谢

3 个答案:

答案 0 :(得分:5)

如果不阻塞整个执行堆栈,则无法从内部调用函数。通过从内部调用函数,您可以有效地阻止它返回,并且由于Javascript是单线程的,所以一切都将停止!

将您的功能更改为:

function slidecokokunanlar() {
    $('#cokokunanlarcontent').html($('#cokokunanlar1').html()).delay(3000)...
    setTimeout(slidecokokunanlar, 0);
}

这允许在不阻止UI的情况下并发执行,从而允许您的页面保持响应。

有关其工作原理的详情,请参阅this article on "chunking"

答案 1 :(得分:2)

这是因为JavaScript doesn't have proper tail calls

你的函数永远在自己的末尾自称。第一个永远不会完成并返回,第二个也不会完成,也不会执行任何一个,直到你用完堆栈并爆炸。

您可以尝试使用setTimeout代替。请参阅example on jsFiddle

编辑您可能不想使用0,除非您确实需要它连续运行。即使使用100,你也可以每秒执行10次这个功能。

function foo(){
  console.log('foo');
  setTimeout(foo, 0);  
}

foo();

答案 2 :(得分:1)

这是一种更清洁的方法。

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