您现在的位置: 365建站网 > 365学习 > js/javascript中setInterval()定时器的设置和清除

js/javascript中setInterval()定时器的设置和清除

文章来源:365jz.com     点击数:135    更新时间:2018-06-12 12:34   参与评论

setInterval()

setInterval的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行:

<button id="btn">0</button>
<script>
var timer = setInterval(function(){
    btn.innerHTML = Number(btn.innerHTML) + 1;
},1000);
btn.onclick = function(){
    clearInterval(timer);
    btn.innerHTML = 0;
}
</script>

HTML5标准规定,setTimeout的最短时间间隔是4ms;setInterval的最短间隔时间是10ms,也就是说,小于10ms的时间间隔会被调整到10ms。

大多数电脑显示器的刷新频率是60HZ,大概相当于每秒钟重绘60次。因此,最平滑的动画效的最佳循环间隔是1000ms/60,约等于16.6ms。

为了节电,对于那些不处于当前窗口的页面,浏览器会将时间间隔扩大到1000ms。另外,如果笔记本电脑处于电池供电状态,Chrome和IE10+浏览器,会将时间间隔切换到系统定时器,大约是16.6ms。


setInterval()的问题

使用setInterval()的问题在于,定时器代码可能在代码再次被添加到队列之前还没有完成执行,结果导致定时器代码连续运行好几次,而之间没有任何停顿。而JavaScript引擎对这个问题的解决是:当使用setInterval()时,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。这确保了定时器代码加入到队列中的最小时间间隔为指定间隔。

但是,这样会导致两个问题:

某些间隔被跳过;

多个定时器的代码执行之间的间隔可能比预期的小

假设,某个onclick事件处理程序使用setInterval()设置了200ms间隔的定时器。如果事件处理程序花了300ms多一点时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过某间隔的情况:


理解setTimeout和setInterval

例子中的第一个定时器是在205ms处添加到队列中的,但是直到过了300ms处才能执行。当执行这个定时器代码时,在405ms处又给队列添加了另一个副本。在下一个间隔,即605ms处,第一个定时器代码仍在运行,同时在队列中已经有了一个定时器代码的实例。结果是,在这个时间点上的定时器代码不会被添加到队列中


理解setTimeout和setInterval


例子中的第一个定时器是在205ms处添加到队列中的,但是直到过了300ms处才能执行。当执行这个定时器代码时,在405ms处又给队列添加了另一个副本。在下一个间隔,即605ms处,第一个定时器代码仍在运行,同时在队列中已经有了一个定时器代码的实例。结果是,在这个时间点上的定时器代码不会被添加到队列中


迭代setTimeout

为了避免setInterval()定时器的问题,可以使用链式setTimeout()调用:

setTimeout(function fn(){
    setTimeout(fn,interval);
},interval);

这个模式链式调用了setTimeout(),每次函数执行的时候都会创建一个新的定时器。第二个setTimeout()调用当前执行的函数,并为其设置另外一个定时器。这样做的好处是,在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔。而且,它可以保证在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行


使用setInterval()


<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;position:absolute;left:0;"></div>
<script>
    myDiv.onclick = function(){
        var timer = setInterval(function(){
            if(parseInt(myDiv.style.left) > 200){
                clearInterval(timer);
                return false;
            }
            myDiv.style.left = parseInt(myDiv.style.left) + 5 + 'px';    
        },16);    
    }
</script>


使用链式setTimeout()

<div id="myDiv" style="height: 100px;width: 100px;background-color: pink;position:absolute;left:0;"></div>
<script>
    myDiv.onclick = function(){
        setTimeout(function fn(){
            if(parseInt(myDiv.style.left) <= 200){
                setTimeout(fn,16);    
            }else{
                return false;
            }
            myDiv.style.left = parseInt(myDiv.style.left) + 5 + 'px';    
        },16);    
    }
</script>


setInterval 不同于setTimeout,setInterval会无限反复执行,如果要让setInterval停止执行该怎么做呢?

只需要把setInterval()赋值给一个变量,然后clearInterval()这个变量即可停止。

例如:

var timesRun = 0;
var interval = setInterval(function(){
timesRun += 1;
if(timesRun === 60){
clearInterval(interval);
}
//do whatever here..
}, 2000);
var startTime = new Date().getTime();
var interval = setInterval(function(){
if(new Date().getTime() - startTime > 60000){
clearInterval(interval);
return;
}
//do whatever here..
}, 2000);





如上面的例子所示:

使用一个变量 var timer = setInterval(fun,2000);

将setInterval赋值给一个变量,要停止的时候,只需要使用clearInterval(timer);即可停止上面的这个每个两秒循环执行fun的这个函数了。


发送短信验证码是一个非常常见的功能,

现在的需求是:

用户点击“获取验证码”的时候,请求后端接口,发送短信验证码,

按钮置灰不可点,变成“重发(xx s)”, 40s后,出现“发送语音验证码”按钮,

60s后,“重发”按钮再变成“获取验证码”


肯定是要用 setInterval() 了,但是这里边就涉及到使用 clearInterval() 清除周期性执行,

见示例:

<a class="c-right-btn btn-send-captcha">获取验证码</a>  
<a class="c-right-btn btn-send-captcha-disable" style="display:none;"></a>

 

window._timer = 60;  
        var _send = setInterval(function(){  
            console.log(_timer);  
            if(_timer > 0){  
                $(".btn-send-captcha").hide();  
                $(".btn-send-captcha-disable").show().text("重发(" + _timer + "s)");  
                _timer --;  
            }  
            if(_timer == 40){  
                $(".btn-send-voice").show();  
            }  
            if(_timer <= 0){  
                $(".btn-send-captcha-disable").text("").hide();  
                $(".btn-send-captcha").show();  
                window.clearInterval(_send);  
                _timer = 60;  
                return false;  
            }  
        }, 1000);

  



如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛


发表评论 (135人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
用户名: 验证码: 点击我更换图片
最新评论
------分隔线----------------------------