放弃setInterval-说说定时器

上述事件循环机制的核心是:JS引擎线程和事件触发线程前端

但事件上,里面还有一些隐藏细节,譬如调用setTimeout后,是如何等待特定时间后才添加到事件队列中的?web

是JS引擎检测的么?固然不是了。它是由定时器线程控制(由于JS引擎本身都忙不过来,根本无暇分身)浏览器

为何要单独的定时器线程?由于JavaScript引擎是单线程的, 若是处于阻塞线程状态就会影响记计时的准确,所以颇有必要单独开一个线程用来计时。函数

何时会用到定时器线程?当使用setTimeoutsetInterval,它须要定时器线程计时,计时完成后就会将特定的事件推入事件队列中。学习

 

  • 即使是0毫秒后就推入事件队列,可是W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。(不过也有一说是不一样浏览器有不一样的最小时间设定)优化

  • 就算不等待4ms,就算假设0毫秒就推入事件队列,时间也不必定准确。由于只有可执行栈内空了后才会主动读取事件队列。线程

那是用setTimeout仍是setInterval?

 

用setTimeout模拟按期计时和直接用setInterval是有区别的。code

由于每次setTimeout计时到后就会去执行,而后执行完内部代码后,因此这里可能有一段时间后才会继续setTimeout,中间就多了偏差(偏差多少与代码执行时间有关)队列

而setInterval则是每次都精确的隔一段时间推入一个事件(可是,事件的实际执行时间不必定就准确,还有多是这个事件还没执行完毕,下一个事件就来了)事件

并且setInterval有一些比较致命的问题就是:

  • 累计效应(上面提到的),上一个还没执行完。

就会致使定时器代码连续运行好几回,而之间没有间隔。
就算正常间隔执行,多个setInterval的代码执行时间可能会比预期小(由于代码执行须要必定时间)

  • 譬如像iOS的webview,或者Safari等浏览器中都有一个特色,在滚动的时候是不执行JS的,若是使用了setInterval,会发如今滚动结束后会执行屡次因为滚动不执行JS积攒回调,若是回调执行时间过长,就会很是容器形成卡顿问题和一些不可知的错误(听说setInterval自带优化,不会重复添加回调)

  • 并且把浏览器最小化显示等操做时,setInterval并非不执行程序,

它会把setInterval的回调函数放在队列中,等浏览器窗口再次打开时,一瞬间所有执行时

因此,鉴于这么多但问题,目前通常认为的最佳方案是:用setTimeout模拟setInterval,或者特殊场合直接用requestAnimationFrame

补充:JS高程中有提到,JS引擎会对setInterval进行优化,若是当前事件队列中有setInterval的回调,不会重复添加。不过,仍然是有不少问题。。。

 

最后留一个做业 setInterval 会不会累计,验证他的执行特色。

 

到这里我们这个系列快说完了,还有最后一节,如今不知道你们听了这些后有什么感想,不知道对你们有么有帮助。我自认为啊有些地方说的不够明确和透彻。不少都是把点带出来了,有些细节可能还须要你们继续学习,查一些资料进行深刻研究或者关注下重度前端这个号 我本身的号,分享的内容都有文字版的,也包括我平常工做中的一些技术总结和积累。今天太晚了,最后一节我先想一想怎么说吧。

 

再见,各位。

相关文章
相关标签/搜索