资讯专栏INFORMATION COLUMN

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

impig33 / 3106人阅读

摘要:按照定时器的时间间隔,处第二个函数加入到事件队列,但此时正在执行,所以只能等待。这样做的好处是,在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔。

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!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91980.html

相关文章

  • 结合源码彻底理解 react事件机制原理 02 - 对于合成理解

    摘要:前言这是事件机制系列文章的第二篇对于合成的理解,咱们就来说说合成这个名词。在给注册事件的时候也是对兼容性做了处理。总结以上就是我对于合成这个名词的理解,其实内部还处理了很多,我只是略微简单的举了几个栗子。 showImg(https://segmentfault.com/img/bVbtvI3?w=1048&h=550); 前言 这是react事件机制系列文章的第二篇-对于合成的理解,...

    nihao 评论0 收藏0
  • 深度学习解决机器阅读理解任务研究进展

    摘要:深度学习近年来在中广泛使用,在机器阅读理解领域也是如此,深度学习技术的引入使得机器阅读理解能力在最近一年内有了大幅提高,本文对深度学习在机器阅读理解领域的技术应用及其进展进行了归纳梳理。目前的各种阅读理解任务中完形填空式任务是最常见的类型。 关于阅读理解,相信大家都不陌生,我们接受的传统语文教育中阅读理解是非常常规的考试内容,一般形式就是给你一篇文章,然后针对这些文章提出一些问题,学生回答这...

    flybywind 评论0 收藏0
  • 关于神经网络需要注意概念总结

    摘要:之前接触并了解过神经网络的相关概念,但是并没有做过任何系统的总结,这一段时间借此总结一下相关的概念对于神经网络的入门概念来说最重要的是一些相关的理解性概念反向传播激活函数正则化以及等。 之前接触并了解过神经网络的相关概念,但是并没有做过任何系统的总结,这一段时间借此总结一下相关的概念;对于神经网络的入门概念来说最重要的是一些相关的理解性概念:反向传播、激活函数、正则化以及BatchNo...

    Tecode 评论0 收藏0
  • 关于神经网络需要注意概念总结

    摘要:之前接触并了解过神经网络的相关概念,但是并没有做过任何系统的总结,这一段时间借此总结一下相关的概念对于神经网络的入门概念来说最重要的是一些相关的理解性概念反向传播激活函数正则化以及等。 之前接触并了解过神经网络的相关概念,但是并没有做过任何系统的总结,这一段时间借此总结一下相关的概念;对于神经网络的入门概念来说最重要的是一些相关的理解性概念:反向传播、激活函数、正则化以及BatchNo...

    plus2047 评论0 收藏0
  • Android研发进阶之路

    摘要:市面上也多是谈论知识图谱,缺少体系和成长节奏感,特此编写一份研发进阶之路,希望能对大家有所帮助。中级而到达中级就需要付出一些努力了,需要了解更多知识,可以仿照开源库去造轮子练习。能够熟练掌握开源库的使用,如图片库网络库工具等。前言 移动研发火热不停,越来越多人开始学习android开发。但很多人感觉入门容易成长很难,对未来比较迷茫,不知道自己技能该怎么提升,到达下一阶段需要补充哪些内容。市...

    idisfkj 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<