在超时循环中运行一个函数

时间:2012-04-05 15:15:55

标签: javascript jquery

我有以下代码:

// After 8 seconds change the slide...
        var timeout = setTimeout("changeSlide()", 8000);

        $('div.slideshow').mouseover(function() {

            // If the user hovers the slideshow then reset the setTimeout
            clearTimeout(timeout);
        });

        $('div.slideshow').mouseleave(function() {

            clearTimeout(timeout);
            var timeout = setTimeout("changeSlide()", 8000);

        });

我想要发生的是让函数changeSlide在循环中运行每8秒,除非有人悬停幻灯片div。当他们移除光标然后再次执行超时!

然而,循环只发生一次,悬停不会停止超时或再次启动:/

编辑:

这循环很好,但悬停时打开和关闭会导致函数多次运行:

// After 8 seconds change the slide...
        var timeout = setInterval(changeSlide, 2000);

        $('div.slide').mouseover(function() {

            // If the user hovers the slideshow then reset the setTimeout
            clearInterval(timeout);
        });

        $('div.slide').mouseleave(function() {

            clearInterval(timeout);
            var timeout = setInterval(changeSlide, 2000);

        });

5 个答案:

答案 0 :(得分:1)

指定setTimeout(或setInterval)时,它返回一个值,然后用于clearTimeout和clearInterval。正确用法如下:

var timeout = setTimeout(changeSlide, 8000);
clearTimeout(timeout);

另请注意我使用的是clearTimeout,而不是clearInterval。

你还会注意到我没有在'changeSlide'周围加上引号,而且我放弃了parens。将字符串传递给setTimeout时,使用eval()。通常建议避免使用eval()。所以,相反,我们传递它直接引用函数(没有引号)。我们使用parens,因为它实际上会立即调用changeSlide(),而不是将执行推迟到setTimeout(并且将作为setTimeout的参数传递给changeSlide()的结果)

编辑:要使其连续运行,您必须在每次changeSlide调用后再次调用setTimeout 。 setTimeout运行一次。作为替代方案,您可以使用自动重复的setInterval。 setInterval的一个警告是,如果间隔太短并且它调用的回调需要很长时间才能运行,那么最终可能会排队等待一个接一个地执行的间隔,而不会有任何延迟。 8秒的间隔可能不会遇到这个问题。

编辑2:

var timeout;
var changeSlide = function(){
   // do something to change slides
   clearTimeout(timeout);
   timeout = setTimeout(changeSlide, 8000);
}

// queue up the first changeSlide, all others happen inside changeSlide
timeout = setTimeout(changeSlide, 8000);

$('div.slideshow').mouseleave(function()  {
    clearTimeout(timeout);
    var timeout = setTimeout(changeSlide, 8000);
});

答案 1 :(得分:1)

这里有几个问题。首先,当您设置超时时,如果您可能想要将其停止,则需要将该函数调用的返回值存储到变量中。

    var slide_timer = setTimeout(changeSlide, 8000);

其次,当你调用clearTimeout(而不是clearInterval)时,你需要传递一个参数。什么说法?您调用setTimeout

时存储的变量
        clearTimeout(slide_timer);

第三,当你使用setTimeout时,它只会触发一次。 setInterval会继续发射,然后你会使用clearInterval来阻止它。

使用间隔而非超时的时间安排存在问题。浏览器以不同的方式对待它们,您的代码可能很重要,以了解差异并使用正确的方法。如果你使用间隔,因为它们只发射一次,你每次发射时都必须重新建立超时。

var slide_timer = setTimeout(function () {
    changeSlide();
    var slide_timer = setTimeout(changeSlide, 8000);
}, 8000);

OR

var slide_timer = setTimeout(changeSlide, 8000);
...
function changeSlide() {
   ... your code ...
    var slide_timer = setTimeout(changeSlide, 8000);
}

(我更喜欢前一种方法)

最后,无论是使用超时还是间隔,都不要将字符串传递给setTimeout,传递函数引用。请参阅上面的示例代码,或者像这样:

var slide_timer = setTimeout("changeSlide()", 8000); // <--- DON'T
var slide_timer = setTimeout(changeSlide, 8000);     // <--- DO
var slide_timer = setTimeout(function () {           // <--- DO
    changeSlide() ;
    // other script
}, 8000); 

全部放在一起:

// After 8 seconds change the slide...
    var slide_timer = setTimeout(changeSlide, 8000);
    $('div.slideshow').hover(function() {
        // If the user hovers the slideshow then reset the setTimeout
        clearTimeout(slide_timer);
    }, function() {
        slide_timer = setInterval(changeSlide, 8000);
    });

<强>文档

答案 2 :(得分:0)

我认为你需要setInterval而不是setTimeout,因为:

  

setTimeout(表达式,超时);在超时后运行代码/函数

     

setInterval(表达式,超时);以间隔运行代码/函数,它们之间的超时长度

答案 3 :(得分:0)

最后这种方法效果最好(但我不接受这个作为我的答案,因为有人帮助我达到了这一点)

// After 8 seconds change the slide...
    var slide_timer = setInterval(changeSlide, 2000);
    $('div.slideshow').hover(function() {
        // If the user hovers the slideshow then reset the setTimeout
        clearInterval(slide_timer);

    }, function() {
        slide_timer = setInterval(changeSlide, 2000);
    });

答案 4 :(得分:0)

您的问题可能是鼠标悬停事件。鼠标悬停事件会冒泡,因此如果您有嵌套的HTML结构,则可能会多次调用该事件。 如果您使用的是jQuery ,则应使用 mousenter 事件,该事件只会为该元素调用一次。

另一方面,使用setTimeout模式而不是使用setInterval。像这样:

    //Immediately Invoked Function Expression that gets called immediately
    (function() {
        //Make the initial call to your setTimeout function
        repeat();
        //Function will constantly be called
        function repeat() {
            setTimeout(function() {
                //(Put your conditional logic here)
                console.log('test');
                repeat();
            }, 2000);
        }
    })();