浅谈对于“不用setInterval,用setTimeout”的理解

 更新时间:2019年08月28日 09:33:37   作者:小利子  
这篇文章主要介绍了浅谈对于“不用setInterval,用setTimeout”的理解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

JavaScript高级程序设计(第三版)(以下简称红宝书)22.3高级定时器中详细介绍了定时器setTimeout和setInterval,看完书后,深入理解了二者的区别,结合前辈们给我的建议“用setTimeout,不要用setInterval”,写下此文,分析这个建议的合理性。
这两个家伙看上去长得差不多,func是要执行的函数,interval是时间间隔。

setTimeout(func,interval)
setInterval(func,interval)

关于时间间隔,红宝书中这么说:

设定一个 150ms 后执行的定时器不代表到了 150ms 代码就立刻执行,它表示代码会在 150ms 后被加入到队列中。如果在这个时间点上,队列中没有其他东西,那么这段代码就会被执行。

对于这个时间间隔的理解非常重要!步入正题,为何不用setInterval,因为它可能会带来两个问题:

  • “丢帧”现象
  • 不同定时器的代码的执行间隔比预期小

一图胜千言,如下图所示,让我们跟着时间线看看这样的问题怎么发生的。假定一个场景,在click事件中设置了setInterval(func,500),假设click事件和定时器内函数的执行时间都是1s,为了方便陈述,我把不同时间触发的func取了不同的名字,实际上接下来的func1=func2=func3=func。在0s处触发click事件,click事件执行,在0.2s处触发定时器,0.7s处第一个函数func1加入到事件队列,但由于JS引擎是单线程的,click事件还在执行,所以func1等待着,等到1s处,click事件执行完毕,fun1才开始执行。按照定时器的时间间隔,1.2s处第二个函数func2加入到事件队列,但此时fun1正在执行,所以func2只能等待。0.5s后,也就是1.7s处,第三个函数func理应加入事件队列,但是JS引擎做了一个事情:

当使用 set Interval()时,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。

在1.7s处,func1在执行,func2在队列里等待执行,func2就是该定时器的代码实例,按照JS引擎的处理,func3不会加入到事件队列里,更别说执行了,这就导致出现了“丢帧”现象。而在图中也可以注意到,func1执行完毕,线程空闲了,func2就可以执行了,这就使得func1和func2之间的执行没有时间间隔,这跟我们所预期的500ms产生一次结果是不同的。

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

setTimeout(function(){
  //do something
  setTimeout(arguments.callee,interval);
},interval)

用setTimeout方法的话,上面假设的场景就发生了改变,如下图所示,在0s处触发click事件,click事件执行,在0.2s处触发定时器,0.7s处第一个函数func1加入到事件队列,click事件执行了1s,在1s处func1执行,2s处func1执行结束,第二个setTimeout定时器才被触发,0.5s后将函数func2加入队列,此时队列为空,func2开始执行,3.5s处func2执行结束,又一个setTimeout定时器被触发,0.5s后将函数func3加入队列,此时队列为空,func3开始执行。。。

通过上面这个场景,我们能知道当需要用定时器来设置一个操作重复执行,并且这个操作需要执行一定的时间,记得用setTimeout,不用setInterval!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 微信小程序实现自定义拍摄组件

    微信小程序实现自定义拍摄组件

    这篇文章主要为大家详细介绍了微信小程序实现自定义拍摄组件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • js流动式效果显示当前系统时间

    js流动式效果显示当前系统时间

    这篇文章主要为大家详细介绍了js实现流动式时间效果的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • js实现加载页面就自动触发超链接的示例

    js实现加载页面就自动触发超链接的示例

    下面小编就为大家带来一篇js实现加载页面就自动触发超链接的示例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Javascript表达式中连续的 && 和 || 之赋值区别

    Javascript表达式中连续的 && 和 || 之赋值区别

    了区分赋值表达式中出现的连续的 ‘&&’和 ‘||’的不同的赋值含义,做了一个小测试.
    2010-10-10
  • uni-app设置缓存过期时间的操作方法

    uni-app设置缓存过期时间的操作方法

    uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序,本文给大家介绍了uni-app设置缓存过期时间的操作方法,需要的朋友可以参考下
    2024-12-12
  • JS实现一键复制

    JS实现一键复制

    这篇文章主要为大家详细介绍了js实现点击按钮复制文本,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • JS高级技巧(简洁版)

    JS高级技巧(简洁版)

    由于在JS中,所有的函数都是对象,所以使用函数指针十分简单,也是这些东西使JS函数有趣且强大,这里特分享一下
    2018-07-07
  • 使用JS实现图片展示瀑布流效果的实例代码

    使用JS实现图片展示瀑布流效果的实例代码

    下面小编就为大家带来一篇使用JS实现图片展示瀑布流效果的实例代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • 详解JavaScript中哪一种循环最快呢

    详解JavaScript中哪一种循环最快呢

    这篇文章主要介绍了详解JavaScript中哪一种循环最快呢,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • JavaScript中保留小数点后N位方法总结

    JavaScript中保留小数点后N位方法总结

    这篇文章主要为大家详细介绍了JavaScript中保留小数点后N位的几个常用方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-06-06

最新评论