这个函数递归有什么问题? (setTimeout问题)

时间:2010-10-19 13:57:16

标签: javascript jquery recursion timeout marquee

我正在编写一个字幕脚本,因为我不喜欢这样的事实:当大帐篷到达最后一个项目时使用大多数字幕脚本(想到使用ul,所以最后一项是最后一项),它会等到该项目关闭屏幕,然后重置ul的位置,并开始滚动整个agian。

我的方法是创建ul的克隆,在当前ul之后追加它,并开始滚动,然后在完全隐藏后删除原始ul。

除了一件事,这几乎是完美的。当您调用该函数时,它会生成setTimout所需的时间。此setTimout用于创建新的UL并将其设置为移动。

这适用于第一个循环,但随后出现故障。

这有点难以解释,但似乎第二次应该调用超时,而不是等待时间,它只是立即调用自己。有关示例,请参阅http://webspirited.com/marquee.html

一个工作的例子。 javascript代码如下:

var count = 0;
$('document').ready(function () {
    //generate some random rows
    for (var i = 0; i <= 20; i++)
    $('.ulscroll').append('<li>Content ' + i + '</li>');
    //add one row so we can see its the last
    $('.ulscroll').append('<li>Last Item</li>');

    //set the ul's width
    var width = 0;
    $('.ulscroll').children('li').each(function () {
        width += $(this).outerWidth();
    });
    log('ul width: ' + width);
    $('.ulscroll').width(width);

    //activate the marquee              
    marquee('.ulscroll', 1, false);
});

function marquee(id, speed, sub) {
    //next two lines debugging purposes only
    count += 1;
    log('Marquee ran ' + count + ' times');

    //store copy of speed sent it(to pass for recursion)
    var s1 = speed;
    //set speed to 10*
    speed = speed * 10;

    //store parent width, and own width (if sub then add on width of parent div)
    var pwidth = $(id).parent('div').outerWidth();
    var width = (sub ? $(id).width() + pwidth : $(id).width());

    //set timeout
    var t = (width - pwidth) * speed;
    setTimeout(function () {
        var clone = $(id).clone().css('left', pwidth);
        $(id).addClass('oldul');
        $(id).after(clone);
        marquee(id + ':not(.oldul)', s1, true);
    }, t);

    $(id).animate({
        left: '-=' + width
    }, width * speed, 'linear', function () {
        $(this).remove();
    });
}

function log(text) {
    $('#log').append('<div>' + text + '</div>');
}

<小时/> 的解决方案
问题是由选择器传入:not(.ulold); 这是修订后的setTimeout

setTimeout(function(){
  var clone = $(id).clone().css('left', pwidth);
  $(id).addClass('oldul');
  var idx = id.split(':');
  idx = idx[0];
  log('idx: '+idx);
  $(idx).after(clone);
  marquee(idx+':not(.oldul)', s1, true);
},t);

2 个答案:

答案 0 :(得分:0)

问题很可能在于此代码..

    var clone = $(id).clone().css('left', pwidth);
    $(id).addClass('oldul');

你正在重新使用选择器的事实会使事情变得混乱,因为随着时间的推移,原始选择器会匹配很多东西。

在初始通话中使用marquee('.ulscroll:not(.oldul)', 1, false);

答案 1 :(得分:0)

学习使用好的调试器,例如Firebug。您将看到最终动画结束回调(删除与选择器匹配的元素的回调)在匿名超时函数(调用marquee的函数)之前被调用。

示例页面上的代码存在问题(但未在发布的代码中):tout对于marquee的每次调用都是本地的。 clearTimeout(tout)电话无效。

最后,请不要使用选框。它有usability个问题:移动文本更难阅读,导致注意力分散,并且对于某些读者而言总是移动得太快或者对于某些读者来说移动速度太慢。