setInterval计时器不准的问题解决方法


Posted in Javascript onMay 08, 2014

在js中如果打算使用setInterval进行倒数,计时等功能,往往是不准确的,因为setInterval的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行.而下一次触发时间则是在setInterval回调函数执行完毕之后才开始计时,所以如果setInterval内执行的计算过于耗时,或者有其他耗时任务在执行,setInterval的计时会越来越不准,延迟很厉害.

下面的代码可以说明这个问题

var startTime = new Date().getTime(); 
var count = 0; 
//耗时任务 
setInterval(function(){ 
var i = 0; 
while(i++ < 100000000); 
}, 0); 
setInterval(function(){ 
count++; 
console.log(new Date().getTime() - (startTime + count * 1000)); 
}, 1000);

代码里输出了setInterval触发时间和应该正确触发时间的延迟毫秒数
176 
340 
495 
652 
807 
961 
1114 
1268 
1425 
1579 
1734 
1888 
2048 
2201 
2357 
2521 
2679 
2834 
2996 
......

可以看到延迟是越来越严重的.

为了在js里可以使用相对准确的计时功能,我们可以

var startTime = new Date().getTime(); 
var count = 0; 
setInterval(function(){ 
var i = 0; 
while(i++ < 100000000); 
}, 0); 
function fixed() { 
count++; 
var offset = new Date().getTime() - (startTime + count * 1000); 
var nextTime = 1000 - offset; 
if (nextTime < 0) nextTime = 0; 
setTimeout(fixed, nextTime); console.log(new Date().getTime() - (startTime + count * 1000)); 
} 
setTimeout(fixed, 1000);

代码里,通过1000(也就是周期时间)减去当前时间和准确时间的差距,来算出下次触发的时间,从而修正了当前触发的延迟.

下面是输出

186 
200 
230 
271 
158 
899 
900 
899 
900 
899 
899 
899 
902 
899 
418 
202 
232 
266 
145 
174 
192 
214 
242 
268 
149 
179 
214 
......

可以看到虽然触发时间并非绝对准确,但由于每次触发都进行及时修正,所以并没有造成误差积累.
Javascript 相关文章推荐
js下拉菜单语言选项简单实现
Sep 23 Javascript
检测一个函数是否是JavaScript原生函数的小技巧
Mar 13 Javascript
jQuery使用$.ajax进行即时验证实例详解
Dec 11 Javascript
js如何准确获取当前页面url网址信息
Sep 13 Javascript
JavaScript编写检测用户所使用的浏览器的代码示例
May 05 Javascript
如何解决手机浏览器页面点击不跳转浏览器双击放大网页
Jul 01 Javascript
vue.js初学入门教程(1)
Nov 03 Javascript
浅谈关于angularJs中使用$.ajax的注意点
Aug 12 Javascript
详解创建自定义的Angular Schematics
Jun 06 Javascript
Nuxt页面级缓存的实现
Mar 09 Javascript
vue-amap根据地址回显地图并mark的操作
Nov 03 Javascript
vue 实现弹窗关闭后刷新效果
Apr 08 Vue.js
Js Jquery创建一个弹出层可加载一个页面
May 08 #Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
May 08 #Javascript
js 设置缓存及获取设置的缓存
May 08 #Javascript
javascript实现的一个带下拉框功能的文本框
May 08 #Javascript
javascript解析json数据的3种方式
May 08 #Javascript
Javascript异步编程模型Promise模式详细介绍
May 08 #Javascript
JS获取随机数函数可自定义最小值最大值
May 08 #Javascript
You might like
php中time()和mktime()方法的区别
2013/09/28 PHP
将FCKeditor导入PHP+SMARTY的实现方法
2015/01/15 PHP
PHP实现通过strace定位故障原因的方法
2018/04/29 PHP
PDO::prepare讲解
2019/01/29 PHP
兼容主流浏览器的jQuery+CSS 实现遮罩层的简单代码
2014/10/14 Javascript
JS动态修改iframe内嵌网页地址的方法
2015/04/01 Javascript
AngularJS中监视Scope变量以及外部调用Scope方法
2016/01/23 Javascript
jquery ztree异步搜索(搜叶子)实践
2016/02/25 Javascript
JSON 数据详解及实例代码分析
2017/01/20 Javascript
jQuery实现页面倒计时并刷新效果
2017/03/13 Javascript
Node.js 中exports 和 module.exports 的区别
2017/03/14 Javascript
图解Javascript——作用域、作用域链、闭包
2017/03/21 Javascript
微信小程序 侧滑删除(左滑删除)
2017/05/23 Javascript
薪资那么高的Web前端必看书单
2017/10/13 Javascript
Vue的土著指令和自定义指令实例详解
2018/02/04 Javascript
微信小程序实现登录注册tab切换效果
2020/12/29 Javascript
vue中使用vue-cli接入融云实现即时通信
2019/04/19 Javascript
微信小程序通过websocket实时语音识别的实现代码
2020/08/19 Javascript
工作中常用js功能汇总
2020/11/07 Javascript
[05:40]DOTA2荣耀之路6:Wings最后进攻
2018/05/30 DOTA
举例讲解Python的lambda语句声明匿名函数的用法
2016/07/01 Python
python实时分析日志的一个小脚本分享
2017/05/07 Python
python筛选出两个文件中重复行的方法
2018/05/31 Python
使用Python操作FTP实现上传和下载的方法
2019/04/01 Python
python 实现关联规则算法Apriori的示例
2020/09/30 Python
python re模块常见用法例举
2021/03/01 Python
StubHub意大利:购买和出售全球演唱会和体育赛事门票
2017/11/21 全球购物
MaBelle玛贝尔香港官网:香港钻饰连锁店
2019/09/09 全球购物
介绍下WebSphere的安全性
2013/01/31 面试题
工伤事故赔偿协议书
2014/04/15 职场文书
小学生清明节演讲稿
2014/09/05 职场文书
综合素质自我评价怎么写
2014/09/14 职场文书
2015年党员创先争优承诺书
2015/01/22 职场文书
运动会开幕式致辞
2015/07/29 职场文书
安全责任协议书范本
2016/03/23 职场文书
关于springboot配置druid数据源不生效问题(踩坑记)
2021/09/25 Java/Android