谈对“设置超时而不是设置间隔”的理解
JavaScript高级编程(第三版)(以下简称“红皮书”)22.3高级定时器详细介绍了定时器setTimeout和setInterval。看完这本书,我深刻理解了他们之间的差异。结合前辈给我的建议“使用setTimeout,不要使用setInterval”,我写了这篇文章,分析了这个建议的合理性。这两个人长得很像,func是要执行的函数,interval是时间间隔。
Settimeout (func,interval) setinterval (func,interval)关于时间间隔,红皮书上是这么说的:
设置计时器在150毫秒后执行并不意味着代码会在150毫秒后立即执行,它意味着代码会在150毫秒后添加到队列中,如果此时队列中没有其他代码,那么将执行该代码。了解这个时间间隔非常重要!言归正传,为什么不用setInterval,因为它可能会带来两个问题:
“丢帧”现象不同定时器的代码执行间隔比预期的要小,也就是一千字。如下图所示,让我们按照时间线来看看这个问题是如何发生的。在一个场景中,在click事件中设置setInterval(func,500),假设click事件和定时器中函数的执行时间为1s。为了表示方便,我给不同时间触发的func起了不同的名字,但实际上,下一个func1=func2=func3=func。点击事件在0s触发,点击事件执行,定时器在0.2s触发,第一个函数func1在0.7s加入事件队列,但是由于JS引擎是单线程的,点击事件还在执行,func1一直等到1s,当点击事件执行时,func1开始执行。根据定时器间隔,事件队列中增加了1.2s的第二个函数fun 2,但此时fun1正在执行,因此fun 2只能等待。0.5s之后,也就是1.7s,第三个函数func应该加入事件队列,但是JS引擎做了一件事:
当使用set Interval()时,只有当计时器没有其他代码实例时,计时器代码才会添加到队列中。在1.7s,func1正在执行,func2正在队列中等待执行。func2是这个定时器的代码示例。根据JS引擎的处理,func3不会被添加到事件队列中,更不会被执行,导致“丢帧”现象。在图中,我们还可以注意到,在func1执行完毕,线程空闲后,可以执行func2,这使得func1和func2之间的执行没有时间间隔,与500 ms的预期结果不同。
如果使用链式setTimeout调用,每次执行该函数时都会创建一个新的计时器。第二个setTimeout()调用使用arguments.callee获取对当前正在执行的函数的引用,并为其设置另一个计时器。这样做的好处是,在执行之前的计时器代码之前,不会有新的计时器代码插入到队列中,以确保不会缺少间隔。此外,它可以确保在执行下一个定时器代码之前必须等待至少一个指定的时间间隔,从而避免连续操作。代码如下
setTimeout(函数(){//做点什么setTimeout(arguments . calleeper,interval);},interval)使用setTimeout方法,上面假设的场景已经改变。如下图所示,点击事件在0s触发执行,定时器在0.2s触发,第一个函数func1在0.7s加入事件队列,点击事件执行1s,func1在1s执行,2s结束。第二个setTimeout定时器被触发,0.5s后,func2加入队列,当队列为空时,func2开始执行,3.5s后,另一个setTimeout定时器被触发,0.5s后,func3加入队列,当队列为空时,func3开始执行。
通过上面的场景,我们可以知道,当需要一个定时器来设置一个操作重复执行,并且这个操作需要执行一定的时间时,记得使用setTimeout而不是setInterval!
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。
版权声明:谈对“设置超时而不是设置间隔”的理解是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。