倒计时功能在JavaScript实现中的毫秒级时间差调试及思考

在一个脑洞里有个倒计时功能,正在想怎么实现,突然想起一个很关键的问题:

之前一些应用场景的倒计时中我使用了 setTimeout 进行递归处理,setTimeout 和 setInterval 一定是有效率区别的,区别有多大?

然后做一个尝试:

先定义提示方法

function timer(id){ console.timeEnd(id); console.time(id); setTimeout('timer("'+id+'")',1000); }

首先定义一下setTimeout的循环计时器。

function timer2(id){ console.timeEnd(id); console.time(id); }

然后定义一下setInterval中循环的方法。

启动!

timer('setTimeout'); setInterval('timer2("interval")',1000)

五年过去了……

如图所示:
运行截图

根据图上打印的日志情况可以粗略猜到了,setInterval计时1000的时候如果因为机器性能等影响到的时候(我在测试的过程中左右切换应用和进行了其他操作),会自己进行一些调节性的操作,很鸡贼;setTimeout就很憨厚了,踏踏实实计时,一次做慢了无所谓下次该咋样还咋样,这种着眼现实的精神很值得我们学习(鼓掌)。

深入一步

刚刚的毕竟是猜测,我们可以继续去研究下它的更向下一些的原理。首先刚刚的demo就不是特别完善,于是我又参考 StackOverflow 的一个回答优化了下撸了另一个可视化程度比较好的 点击查看demo,有兴趣的小伙伴可以点击去看一下。

测试的结果和之前是一样的,都是interval出现了“效率更高一点”的样子。

然后在JavaScriptInfo上查了下资料,资料中显示了如下两张图:

jsinfo-pic1

此图为setInterval(function_name,100)的执行图,

jsinfo-pic2

此图为setTimeout(function() {...}, 100);的递归执行图。

这里给的解释说明了几个事情:

  • 两个计时器时间上的准确是没有问题的,也不存在合理微小延迟的说法
  • setInterval的计时器触发后即刻开始下次计时,setTimeout的计时器触发后到递归到下次计时之间涉及了业务代码的执行周期,所以相对而言会体现出“用时更长”的感觉

看到这里方才明白,并不是setTimeout有延迟,而是在demo中我忽略掉了两个计时器使用后业务代码的执行时间。

应用

如上所述,两种计时器的差别就在于业务代码执行周期产生的延迟了,也就是说并不是setTimeout不准确,只是他们的用途不完全相同。

在应用过程中,使用其中哪个计时器,要取决于我们的业务代码执行周期何如。比如业务代码运算量极其小、或者只是作为本地监听器,用setInterval会更好用一些;如果业务代码执行周期较长,如定期提交用户操作信息,每次执行过程可能会突然出现执行时间超出计时器本身计时周期的情况,用setTimeout显然更稳妥也更合适。

所以说,还是放弃Baidu,健康搜索吧。

标签: none

添加新评论