Js定时器越走越快的问题

时间: 2019-05-12阅读: 307标签: 定时器JavaScript定时器越走越快的问题

前言:在引用开发中,我们经常需要在页面中执行一些周期性的操作,比如每隔一段时间就执行某一固定的操作。而对于这样的操作,最简单和最高效的实现的方式就是使用setInterval和setTimeout两种方式了。接下来我们就来详细了解一下这两种不同的定时器吧!

之前在项目中写了定时器来做循环播放,但是总是会有越走越快的问题,开始是以为前后的HTML代码拼接的有问题,时间紧急的情况下反复改了很多也没什么效果,后来发现是js定时器的问题,在这里记录一下。

setInterval

俗称:间歇性定时器;功能创建一个定时器,可按照指定的周期(以毫秒计)来调用函数或计算表达式;setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数;注意这种定时器只要创建了就等于启动。

语法: setInterval(函数名,时间)
功能: 每隔参数2的时间内,就调用一次参数1的函数。注意:时间以毫秒来计算的!

如果要关闭setInterval设置的定时器,首先就要获取setInterval返回的ID值,然后通过clearInterval(返回的ID值)来关闭特定的setInterval设置的定时器。

实例:

var timer = window.setInterval(func,5000);
function func(){
        console.log("Hello World");
    }

这里就创建了一个每隔5000毫秒就执行函数名为func的定时器,在函数中执行打印“Hello World”。当然,上面也可以换成为这样来写:

var timer = window.clearInterval(function(){
      console.log("Hello World");
},5000);

两者的功能是一毛一样的,只不过后面的是匿名函数而已!

如果要清除上面的定时器该肿么办呢?我们可以这样来做。

clearInterval(timer);

这里就通过创建定时器时存储在timer中的ID值,进行销毁特定ID的定时器。

关于返回的ID值,我们该怎么看呢?这就相当于在创建一个定时器的同时,我们也赋予了这个定时器一个特定的身份了,就像我们伟大的祖国给予每个人特定的身份证一样,是独一无二的,也代表了我们每个人也是独一无二的,在这个世界就只有一个你这样。你的名字!!!
下面我们利用下面的代码一起来看看定时器的身份证到底是什么鬼!咳咳

<div id="div1" style="position: absolute;left: 20px;top: 20px;width: 50px;height: 50px;background-color: red"></div>
    <script type="text/javascript">
        var timer;
        var div1 = document.getElementById("div1");
        div1.onclick = function(){
            timer = setInterval(function(){
                console.log(timer);
            },1000);
        }
    </script>

这里通过JS获取到id为“div1”的div,给其增加点击事件后,只要点击div后,就会打印当前定时器的id。下面就是div的样式和不断的点击之后打印的结果。

图片 1

timerId.PNG

打印结果可以看出,当我们不断的点击div后,timer的值也在不断的改变,说明了定时器在不断的制造出来,以至于在一定时间内打印的次数在不断的增加,timer的值也被不断新建的定时器赋值。也说明了timer就是定时器的返回值。

当然,我们在实际中遇到的问题远不止如此简单,这就需要我们开动我们灵活的大脑了,誓要将定时器玩弄于手掌之中!成大事者,人也。


setTimeout

相比于上面的间歇式定时器,此种定时器俗称延时定时器,也就是用于在指定的毫秒数后调用函数或计算表达式。就相当于设置了一个定时炸弹,在你设定的特定时间之后,它就会被激活,自行爆炸,爆炸之后它也不会再次爆炸!setTimeout定时器也是这样,其只执行一次。如果要多次调用,请使用 setInterval() 或者自身再次调用 setTimeout()。

** 语法:**setTimeout(函数名,时间);
功能:参数2时间后调用参数1函数
返回值:也是返回定时器的id,可以通过该id关闭定时器

如果要关闭setTimeout设置的定时器,方法原理同setInterval类似,不同的也就是方法名的不同。用的是clearTimeout(参数),后面的参数也就是setTimeout要返回的id值。

实例:

<button onclick="closeTimeout()">关闭延时定时器</button>
    <script type="text/javascript">
        var timer = window.setTimeout(func,5000);
        function func(){
            console.log("Hello World");
        }
        function closeTimeout(){
            window.clearTimeout(timer);   // 关闭延时定时器
        }
    </script>

这里设置了5秒后就会只打印一次的延时定时器,然后给按钮增加了清除定时器的方法,一旦按下button,延时定时器就会被销毁了;不过,需要注意的是如果你在延时定时器销毁之后点击是没有任何效果的,因为延时定时器执行了一次之后它就自动销毁了!(对着setInterval说:看看人家多自觉! setInterval弱弱地说:可是它功能没我强大啊!我默默不说话。。。)

图片 2

不点击按钮5秒后的结果.png

图片 3

5秒之前点击清除定时器后的效果.PNG

其实,在现阶段的开发阶段,setInterval用的还是比setTimeout频繁的。因为每隔一段时间就执行相同的动作,也就是重复相同的动作,在我们的现实生活中还是常常遇见的。


(setinterval)多次初始化

最后简单谈谈定时器的回调:

其1:定时器的回调函数并不是相当于在时间到了就执行,而是有一个主js执行进程,这个进程是页面刚加载的时候页面按照加载顺序执行的js代码,此外还有一个需要在进程空闲的时候执行的代码队列,而我们所说的定时器的回调就是相当于setInterval在特定时间之后把定时器回调放入到空闲队列中(注意,空闲队列有可能还有其它的代码,比如点击事件,因此定时器回调放入的位置不一定是空闲队列的开始位置!)

其2:setInterval有个很烦的地方就是当js主程序空闲时候,执行代码队列里面的代码的时候,如果此时候我们有一个问题,定时器是等到回调执行完,才开始计时进行下次循环呢?还是只要一次计时完毕,插入回调之后不管回调执不执行就开始计时呢?答案显然是后者,这也就是我说setInterval坑比的原因啊,因为这会出现一种情况,当我们插入回调的时候前队列有别的代码在执行,这时候回调肯定是不会执行的,因此如果这个时候限定时间到了会再次插入回调,这个时候如果发现队列中的第一次回调没有执行,那么再次插入的回调浏览器就默认取消(这是以防出现回调连续执行多次的情况)但是这又引发了新的情况就是有些回调是不能取消掉的?

课后练习:

例一:

setTimeout(function(){
      console.log("小马“);
      setTimeout(function(){arguments.callee;},1000);
},1000)

例二:

setInterval(function(){console.log("小马“);},1000);

问一与二的区别?


 var i=0;
function a(){
        t=setTimeout(function(){console.log("小明")},0);
 }
a();
alert(”小红“);

问先显示小明呢?还是小红??还是小强呢???

总结:setInterval和setTimeout是两种功能完全不一样的定时器,只要运用得当,就可以让它完成某些一次性操作或每隔一段时间就执行的操作吧!

使用js定时器(setinterval)首要的问题就是要记得清除,即调用(clearInterval)方法,由于没有使用定时器的经验,我一开始是没有清除定时器,程序每一次初始化的时候都调用一次定时器,之前的定时器实例没有被销毁,新的定时器又开始执行,就会出现1s变0.5s,0.5s变0.25秒的情况,从观感上来看就是定时器“越走越快”了。

这个过程可以用几行简单的代码模拟一下

label /labelinput type="button" value="启动" /input type="button" value="清除" /

window.onload = function () { var i = 0; var timer; document.getElementById("btnStart").onclick = function () { timer = setInterval( function () { i++; document.getElementById("lblShowNum").innerText = i; }, 1000); } document.getElementById("btnClear").onclick = function () { clearInterval(timer); }}

如果只点击一次“启动”按钮,定时器会正常运行,点击“清除”按钮就可以暂停定时器,但是每一次点击“启动”按钮,都会提高数字的增速,而清除功能也不再起作用,这就是因为在每一次点击“启动”的时候都有新的定时器被创建。

清除(clearInterval)的失效

但为什么清除的方法会失效呢?在代码中我们定义了一个变量timer去接收定时器,对timer操作是不是就能清除定时器了呢?并不是是这样,首先看下setinterval()返回值的说明

一个可以传递给 Window.clearInterval() 从而取消对 code 的周期性执行的值。

这里可以看出这个返回值并不是定时器本身,它只是一个用于传递的返回值,如果想当然的把它当做定时器,以为每次初始化赋值就是新的定时器就错了,我最开始就是这样想的。每一次给timer赋值都是在创建新的定时器对象,而且之前的定时器也并没有被清除,所以这时候调用clearInterval(timer)清除的只是最后一个被创建的定时器对象罢了。

使用上面的例子就可以简单的用肉眼观察效果,先点击一次启动观察速度,再点击第二次,会看到速度有明显的提升,这时候使用清除功能,速度就会回到第一次启动的状态,但是多次点击清除是没有用的,如果想看准确的结果可以将时间打印出来进行比较。

解决方法

看到这里,答案呼之欲出了,很简单,在每次初始化定时器之前先执行清除操作,保证之前的定时器被清除了就不会发生越走越快的情况,所以其实并不是定时器越走越快,而是有多个定时器在执行,定时器里面的程序执行的频率提高了。

window.onload = function () { var i = 0; var timer; document.getElementById("btnStart").onclick = function () { clearInterval(timer); timer = setInterval( function () { i++; document.getElementById("lblShowNum").innerText = i; }, 1000); } document.getElementById("btnClear").onclick = function () { clearInterval(timer); }}

本文由澳门威斯尼人平台登录发布于Web前端,转载请注明出处:Js定时器越走越快的问题

相关阅读