放弃setInterval-说说定时器
上述事件循环机制的核心是:JS引擎线程和事件触发线程
但事件上,里面还有一些隐藏细节,譬如调用setTimeout
后,是如何等待特定时间后才添加到事件队列中的?
是JS引擎检测的么?当然不是了。它是由定时器线程控制(因为JS引擎自己都忙不过来,根本无暇分身)
为什么要单独的定时器线程?因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确,因此很有必要单独开一个线程用来计时。
什么时候会用到定时器线程?当使用setTimeout
或setInterval
时,它需要定时器线程计时,计时完成后就会将特定的事件推入事件队列中。
即便是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-说说定时器的更多相关文章
- Javascript的setTimeOut()和setInterval()的定时器用法
Javascript用来处理延时和定时任务的setTimeOut和setInterval函数应用非常广泛,它们都用来处理延时和定时任务,比如打开网页一段时间后弹出一个登录框,页面每隔一段时间发送异步请 ...
- setInterval && setTimeout || 定时器
来自w3school的解释 定时器setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式. setInterval() 方法会不停地调用函数,直到 clearInterva ...
- JS setInterval 循环定时器的使用 以及动态倒计时展示
例: var setTime = setInterval(function () { ff(); //每秒调用的方法函数 }, 1000); //1000毫秒为1秒 //可使用 clearInterv ...
- setInterval做定时器
<script src="/js/jquery-1.8.3.min.js"></script> <script> $(function () { ...
- Javascript的setTimeOut和setInterval的定时器用法
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式,而setInterval()则是在每隔指定的毫秒数循环调用函数或表达式, 直到 clearInterval把它清除.也就是说se ...
- 关于setInterval()你所不知道的地方
前言:1.使用setInterval()的定时器会把事件运行的时间也包含在内,如果要精确算定时两个任务之间的时间,可以使用setTimeout()替换.2.当异步事件发生时,如mouse click, ...
- setTimeout和setInterval的注意事项
精准问题 setTimeout的问题在于它并不是精准的,例如使用setTimeout设定一个任务在10ms后执行,但是在9ms后,有一个任务占用了5ms的cpu时间片,再次轮到定时器执行时,时间已经过 ...
- Node.js-提供了四种形式的定时器
Node.js提供了四种形式的定时器 global.setTimeout(); //一次性定时器 global.setInterval(); //周期性定时器 global.nextTick(); / ...
- JavaScript定时器详解
假设有以下场景 setTimeout(function timeoutHandler(){ /*Some timeout handle code that runs for 6ms*/ }, 10); ...
随机推荐
- elasticsearch 初步
本文主要内容: 1.elasticsearch的认识(是个啥,能干啥) 2.安装启动.简单集群及关键配置 3.名词解释 4.存取数据,中文分词 ---------------------------- ...
- ruby中的== eql?和equal?区别
原文 http://www.wellho.net/mouth/985_Equality-in-Ruby-eql-and-equal-.html Equality in Ruby - == eql? a ...
- EntityFrameWork Code First 一对多关系处理
场景1: 一个文章类别(Category)下含有多篇文章(Article),而某篇文章只能对应一个类别 Article和Category的代码如下: /// <summary> /// 文 ...
- poj 3750 小孩报数问题
小孩报数问题 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11527 Accepted: 5293 Descripti ...
- Android新手常见问题(一)
[1]AAPT2 error: check logs for details File->Settings->Build->Gradle一看path里有中文 最根本的原因是因为use ...
- linux diff(differential) 命令
功能说明:比较文件的差异. 语法:diff [OPTION]... FILES 实例: diff -ur temp1 temp2 diff -ur temp1 temp2 > temp.diff ...
- LVS+keepalived DR模式配置高可用负载均衡集群
实验环境 LVS-Master 10.0.100.201 VIP:10.0.100.203 LVS-Slave 10.0.100.204 WEB1-Tomcat 10.0.2.29 gat ...
- 一个Java小菜鸟的实习之路
博主今年大四,六月份毕业,之前一直对编程感兴趣,于是在大学里自学了Java,(本专业是通信工程).在今年过年的时候,父母让来南方过年,于是博主自己也想着能不能在南方找份java的实习先干着,了解一下行 ...
- 从零实现一个简易的jQuery框架之二—核心思路详解
如何读源码 jQuery整体框架甚是复杂,也不易读懂.但是若想要在前端的路上走得更远.更好,研究分析前端的框架无疑是进阶路上必经之路.但是庞大的源码往往让我们不知道从何处开始下手.在很长的时间里我也被 ...
- jquery报表插件收藏 MARK
Highcharts http://www.hcharts.cn/ 统计报表插件 jquery ui官网 http://jqueryui.com/selectmenu/#custom_render