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多一点时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过某间隔的情况:
例子中的第一个定时器是在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);
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛