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

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

是JS引擎检测的么?当然不是了。它是由定时器线程控制(因为JS引擎自己都忙不过来,根本无暇分身)

为什么要单独的定时器线程?因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确,因此很有必要单独开一个线程用来计时。

什么时候会用到定时器线程?当使用setTimeoutsetInterval,它需要定时器线程计时,计时完成后就会将特定的事件推入事件队列中。

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

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

那是用setTimeout还是setInterval?

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

因为每次setTimeout计时到后就会去执行,然后执行完内部代码后,所以这里可能有一段时间后才会继续setTimeout,中间就多了误差(误差多少与代码执行时间有关)

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

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

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

就会导致定时器代码连续运行好几次,而之间没有间隔。
就算正常间隔执行,多个setInterval的代码执行时间可能会比预期小(因为代码执行需要一定时间)

  • 譬如像iOS的webview,或者Safari等浏览器中都有一个特点,在滚动的时候是不执行JS的,如果使用了setInterval,会发现在滚动结束后会执行多次由于滚动不执行JS积攒回调,如果回调执行时间过长,就会非常容器造成卡顿问题和一些不可知的错误(据说setInterval自带优化,不会重复添加回调)

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

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

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

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

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

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

再见,各位。

放弃setInterval-说说定时器的更多相关文章

  1. Javascript的setTimeOut()和setInterval()的定时器用法

    Javascript用来处理延时和定时任务的setTimeOut和setInterval函数应用非常广泛,它们都用来处理延时和定时任务,比如打开网页一段时间后弹出一个登录框,页面每隔一段时间发送异步请 ...

  2. setInterval && setTimeout || 定时器

    来自w3school的解释 定时器setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式. setInterval() 方法会不停地调用函数,直到 clearInterva ...

  3. JS setInterval 循环定时器的使用 以及动态倒计时展示

    例: var setTime = setInterval(function () { ff(); //每秒调用的方法函数 }, 1000); //1000毫秒为1秒 //可使用 clearInterv ...

  4. setInterval做定时器

    <script src="/js/jquery-1.8.3.min.js"></script> <script> $(function () { ...

  5. Javascript的setTimeOut和setInterval的定时器用法

    setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式,而setInterval()则是在每隔指定的毫秒数循环调用函数或表达式, 直到 clearInterval把它清除.也就是说se ...

  6. 关于setInterval()你所不知道的地方

    前言:1.使用setInterval()的定时器会把事件运行的时间也包含在内,如果要精确算定时两个任务之间的时间,可以使用setTimeout()替换.2.当异步事件发生时,如mouse click, ...

  7. setTimeout和setInterval的注意事项

    精准问题 setTimeout的问题在于它并不是精准的,例如使用setTimeout设定一个任务在10ms后执行,但是在9ms后,有一个任务占用了5ms的cpu时间片,再次轮到定时器执行时,时间已经过 ...

  8. Node.js-提供了四种形式的定时器

    Node.js提供了四种形式的定时器 global.setTimeout(); //一次性定时器 global.setInterval(); //周期性定时器 global.nextTick(); / ...

  9. JavaScript定时器详解

    假设有以下场景 setTimeout(function timeoutHandler(){ /*Some timeout handle code that runs for 6ms*/ }, 10); ...

随机推荐

  1. JDK,JRE,JVM的基础理解

    1.JVM -- java virtual machine JVM就是我们常说的java虚拟机,它是整个java实现跨平台的 最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类 ...

  2. python 对象/变量&赋值的几点思考

    python 对象/变量 对象 Every object has an identity, a type and a value. An object's identity never changes ...

  3. PHP中判断字符串是否包含某个字符时,建议使用正则表达式preg_match()

    判断字符串中是否包含 某个字符时,在java中时直接使用 indexOf()来判断的 在php中好像也要对应的,strpos(),stripos() 不过每次我用的都很不爽,老是出现各种各样的小问题, ...

  4. C运算符总结

    算术运算符 加减 + - 自左向右 +-同级 乘除取模 * % / 自左向右 高于+ - 自加自减 ++ -- 右结合性 高于基本算术运算符 正负 -+ 自右向左 跟++ --同级 赋值运算符 赋值 ...

  5. [转]前端构建工具gulpjs的使用介绍及技巧

    本文转自:http://www.cnblogs.com/2050/p/4198792.html gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非 ...

  6. vuex 实现vue中多个组件之间数据同步以及数据共享。

    http://pan.baidu.com/s/1hrJfpli  demo下载地址 前言 在一些项目中有很多数据状态之间要实现数据共享状态共享,例如购物车的数据.用户的登录状态等等.vue父元素是可以 ...

  7. 关于webApi使用session

    1.关于webApi使用session 在Global.asax中注册session添加以下代码 public override void Init() { //开启session this.Post ...

  8. Lucene学习之四:Lucene的索引文件格式(2)

    本文转载自:http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623599.html  略有删减和补充 四.具体格式 上面曾经交代过,L ...

  9. 流畅的python和cookbook学习笔记(六)

    1.同时迭代多个序列(zip(函数)) 使用zip()函数可以同时迭代多个序列. >>> X = [1, 2, 3, 4, 5, 6] >>> Y = [121, ...

  10. hdu 3091 Necklace 状态压缩dp *******

    Necklace Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)Total ...