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 相关文章推荐
利用javascript实现一些常用软件的下载导航
Aug 03 Javascript
javascript闭包的理解和实例
Aug 12 Javascript
javascript模拟php函数in_array
Apr 27 Javascript
jQuery中prepend()方法使用详解
Aug 11 Javascript
js捕捉键盘事件和按键键值的方法
Oct 10 Javascript
简单实现JS倒计时效果
Dec 23 Javascript
JavaScript实现的浏览器下载文件的方法
Aug 09 Javascript
Vue中的字符串模板的使用
May 17 Javascript
vue权限问题的完美解决方案
May 08 Javascript
JavaScript实现英语单词题库
Dec 24 Javascript
vue点击标签切换选中及互相排斥操作
Jul 17 Javascript
OpenLayers3实现测量功能
Sep 25 Javascript
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实现文件安全下载
2006/10/09 PHP
php录入页面中动态从数据库中提取数据的实现
2006/10/09 PHP
解析PHP将对象转换成数组的方法(兼容多维数组类型)
2013/06/21 PHP
php文件服务实现虚拟挂载其他目录示例
2014/04/17 PHP
destoon二次开发常用数据库操作
2014/06/21 PHP
php 在线导入mysql大数据程序
2015/06/11 PHP
PHP实现将MySQL重复ID二维数组重组为三维数组的方法
2016/08/01 PHP
PHP实现chrome表单请求数据转换为接口使用的json数据
2021/03/04 PHP
基于jquery的3d效果实现代码
2011/03/23 Javascript
javascript中的继承实例代码
2011/04/27 Javascript
Extjs中使用extend(js继承) 的代码
2012/03/15 Javascript
EasyUI 中 MenuButton 的使用方法
2012/07/14 Javascript
基于jQuery判断两个元素是否有重叠部分的代码
2012/07/25 Javascript
js判断游览器类型及版本号的代码
2014/05/11 Javascript
IE6中链接A的href为javascript协议时不在当前页面跳转
2014/06/05 Javascript
javascript中实现兼容JAVA的hashCode算法代码分享
2020/08/11 Javascript
JS实现一个按钮的方法
2015/02/05 Javascript
JS+CSS实现DIV层的展开、收缩效果
2016/01/28 Javascript
分享自己用JS做的扫雷小游戏
2016/02/17 Javascript
js控制台输出的方法(详解)
2016/11/26 Javascript
微信小程序分享功能之按钮button 边框隐藏和点击隐藏
2018/06/14 Javascript
从零开始学习搭建React脚手架项目
2018/08/23 Javascript
Nuxt.js SSR与权限验证的实现
2018/11/21 Javascript
React通过redux-persist持久化数据存储的方法示例
2019/02/14 Javascript
jQuery中使用validate插件校验表单功能
2019/05/24 jQuery
vue 实现购物车总价计算
2019/11/06 Javascript
python爬虫实现教程转换成 PDF 电子书
2017/02/19 Python
python爬虫把url链接编码成gbk2312格式过程解析
2020/06/08 Python
python 如何将office文件转换为PDF
2020/09/22 Python
日本最大的旅游网站:Rakuten Travel(乐天旅游)
2018/08/02 全球购物
美国室内和室外装饰花盆购物网站:ePlanters
2019/03/22 全球购物
Genny意大利官网:意大利高级时装品牌
2020/04/15 全球购物
什么是动态端口(Dynamic Ports)?动态端口的范围是多少?
2014/12/12 面试题
公司领导九九重阳节发言稿2014
2014/09/25 职场文书
用position:sticky完美解决小程序吸顶问题的实现方法
2021/04/24 HTML / CSS
MySQL完整性约束的定义与实例教程
2021/05/30 MySQL