理解由setTimeout和clearTimeout组成的循环函数

时间:2013-03-24 10:18:31

标签: javascript jquery settimeout

我正在制作一个使用setTimeoutclearTimeout的简单fadeIn / fadeOut循环动画。到目前为止,这是我的代码:

HTML:

<p><span>loading...</span></p>
<a href="#" id="btn">STOP</a>

的Javascript(jQuery1.9.1):

var _timer;
var _timerArr = [];

var loaderBlink = function() {
    $('p').find('span').fadeTo(200,.4).fadeTo(200,1,function() {
        _timer = setTimeout(function() { loaderBlink() }, 200);
        _timerArr.push(_timer);
        //console.log('loading...');
    });
};

var clearTimer = function() {
    $.each(_timerArr, function(i,val) {
        clearTimeout(val);
        console.log(val);
    });

    $('#btn').remove();
    $('p').fadeOut('fast');

    return false;
};

$('#btn').on('click', function() {
    clearTimer();
});

loaderBlink();

DEMO:http://jsfiddle.net/nori2tae/MW9E8/

问题在于,即使我将所有计时器推入阵列以便之后通过单击“停止”按钮清除它们,有时计时器也会停止并继续运行。

可能我不完全理解setTimeoutclearTimeout的概念。我需要一些解决方案,并帮助理解这两个功能。

4 个答案:

答案 0 :(得分:2)

这是一个setIntevall版本:

编辑:它运行良好,但你必须使用函数loaderBlink()包装计时器;再次,错误地删除了它,还没有足够的咖啡。

var _timer;

_timer = setInterval(function () {
            $('p').find('span').fadeTo(200,.4).fadeTo(200,1);
            console.log('loading...');
        }, 400);


var clearTimer = function() {
    clearInterval(_timer);

    $('#btn').remove();
    $('p').fadeOut('fast');

    return false;
};

$('#btn').on('click', function() {
    clearTimer();
});

http://jsfiddle.net/XHUTV/2/

答案 1 :(得分:1)

保存对数组中所有定时器的引用没有多大意义 - 定时器没有连续运行,因此仅将最新的定时器存储在单个数组中就足够了。你只需要停止最后一个,其他一切都已经停止了。

我怀疑当动画运行时点击某个时刻计时器不会停止,所以按钮会停止除了尚未启动的计时器之外的所有计时器,因为动画队列仅在动画停止时启动它。

无论如何,如果没有计时器,这实际上会更简单,更可靠。

var blink = true;

var loaderBlink = function() {
    if( blink ) {
        $('p').find('span').delay( 200 ).fadeTo(200,.4).fadeTo(200,1,function() {
            loaderBlink();
            console.log('loading...');
        });
    }
};

$('#btn').on('click', function() {    
    blink = false;
    $(this).remove();
    $('p').stop().fadeOut('fast');

    return false;
});

loaderBlink();

操作与原始代码略有不同:200毫秒延迟是在动画循环开始时而不是在它之后,但我认为这不是问题。 .stop()确保循环不会重新开始。

演示:http://jsfiddle.net/WAprd/17/

答案 2 :(得分:1)

你解决这个问题的方法有点不对 - 你看到你定义的时间是200ms - 这段时间很短,在代码响应你的点击之前,下一个计时器会继续进行,所以有时候它的工作有时它不是。 同时保存数组中的所有interval_id没有任何意义,因为setTimeout只发生一次(与setInterval相反)。您需要做的是使用标志并关闭单个计时器ID:http://jsfiddle.net/MW9E8/2/

var _timer;
var _timerArr = [];
var fading;

var loaderBlink = function() {
    if(fading){
        $('p').find('span').fadeTo(200,.4).fadeTo(200,1,function() {
            interval_id = setTimeout(function() { loaderBlink() }, 200);
           // _timerArr.push(_timer);
            console.log('loading...');
        });
    }
};

var clearTimer = function() {
    /*
    $.each(_timerArr, function(i,val) {

        console.log(val);
    });
    */    
    clearTimeout(interval_id);
    fading = false;

   // $('#btn').remove();
   // $('p').fadeOut('fast');

    return false;
};

$('#btn').on('click', function() {
    clearTimer();
});

fading = true;
loaderBlink();

答案 3 :(得分:1)

如果你正在为动画使用jQuery,你可以继续使用jQuery来处理其他一切......不需要混合使用setIntervalssetTimeouts

<强>拨弄

http://jsfiddle.net/QNMkp/

<强>标记

<span id="loading">Loading...</span>

<button id="stop">Stop!</button>

<强> JS

$(function(){

    var fadeLoading;

    (fadeLoading = function(){
        $('#loading:not(.stopped)')
            .fadeTo(200,0.4)
            .fadeTo(200,1, fadeLoading) /// you can just loop this
        ;
    })();

    $('#stop').click(function(){
        $('#loading')
            .addClass('stopped') /// add a class to stop new fade starting
            .stop() /// stop existing animations
            .fadeTo(200,1) /// fade loading up to 100%
        ;
    });

});