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获取select标签选中值的两种方式
Jan 09 Javascript
用box固定长宽实现图片自动轮播js代码
Jun 09 Javascript
JavaScript实现鼠标点击后层展开效果的方法
May 13 Javascript
Bootstrap实现登录校验表单(带验证码)
Jun 23 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
Dec 02 Javascript
聊聊JavaScript如何实现继承及特点
Apr 07 Javascript
详解Angular2 关于*ngFor 嵌套循环
May 22 Javascript
JS实现加载时锁定HTML页面元素的方法
Jun 24 Javascript
react-native ListView下拉刷新上拉加载实现代码
Aug 03 Javascript
Vue 组件(component)教程之实现精美的日历方法示例
Jan 08 Javascript
vue2.0 实现导航守卫的具体用法(路由守卫)
May 17 Javascript
详解如何为你的angular app构建一个第三方库
Dec 07 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开发不能违背的安全规则 过滤用户输入
2011/05/01 PHP
php多文件上传实现代码
2014/02/20 PHP
php简单截取字符串代码示例
2016/10/19 PHP
取得一定长度的内容,处理中文
2006/12/20 Javascript
jQuery ul标签下拉菜单演示代码
2010/12/11 Javascript
获取元素距离浏览器周边的位置的方法getBoundingClientRect
2013/04/17 Javascript
JavaScript模块随意拖动示例代码
2014/05/27 Javascript
JavaScript onkeypress事件入门实例(按下或按住一个键盘按键)
2014/10/17 Javascript
jquery实现勾选复选框触发事件给input赋值
2015/02/01 Javascript
js跨域请求数据的3种常用的方法
2015/12/01 Javascript
详解js图片轮播效果实现原理
2015/12/17 Javascript
jQuery图片轮播插件——前端开发必看
2016/05/31 Javascript
Angularjs 制作购物车功能实例代码
2016/09/14 Javascript
Vue数组更新及过滤排序功能
2017/08/10 Javascript
详解react使用react-bootstrap当轮子造车
2017/08/15 Javascript
vue实现商城上货组件简易版
2017/11/27 Javascript
基于React Native 0.52实现轮播图效果
2020/08/25 Javascript
JavaScript如何处理移动端拍摄图片旋转问题
2019/11/16 Javascript
详解JavaScript中的this指向问题
2021/02/05 Javascript
python获取指定网页上所有超链接的方法
2015/04/04 Python
分析Python编程时利用wxPython来支持多线程的方法
2015/04/07 Python
Python实现在matplotlib中两个坐标轴之间画一条直线光标的方法
2015/05/20 Python
Python实现的多线程同步与互斥锁功能示例
2017/11/30 Python
Python使用numpy产生正态分布随机数的向量或矩阵操作示例
2018/08/22 Python
Django 视图层(view)的使用
2018/11/09 Python
详解重置Django migration的常见方式
2019/02/15 Python
Python 随机生成测试数据的模块:faker基本使用方法详解
2020/04/09 Python
Node.js 和 Python之间该选择哪个?
2020/08/05 Python
Python使用for生成列表实现过程解析
2020/09/22 Python
Django restful framework生成API文档过程详解
2020/11/12 Python
Omio中国:全欧洲低价大巴、火车和航班搜索和比价
2018/08/09 全球购物
荷兰最大的儿童服装店:The Kids Republic
2019/04/13 全球购物
大二学习计划书范文
2014/04/27 职场文书
学校证明范文
2015/06/24 职场文书
幼儿园心得体会范文
2016/01/21 职场文书
工伤调解协议书
2016/03/21 职场文书