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 相关文章推荐
在UpdatePanel内jquery easyui效果失效的解决方法
Apr 11 Javascript
jQuery easyui datagrid动态查询数据实例讲解
Feb 26 Javascript
js弹窗返回值详解(window.open方式)
Jan 11 Javascript
基于JS实现PHP的sprintf函数实例
Nov 14 Javascript
基于JavaScript实现根据手机定位获取当前具体位置(X省X市X县X街道X号)
Dec 29 Javascript
JS中使用apply、bind实现为函数或者类传入动态个数的参数
Apr 26 Javascript
gulp-uglify 与gulp.watch()配合使用时报错(重复压缩问题)
Aug 24 Javascript
JavaScript中String对象的方法介绍
Jan 04 Javascript
JavaScript+Html5实现按钮复制文字到剪切板功能(手机网页兼容)
Mar 30 Javascript
vue-cli 引入、配置axios的方法
May 08 Javascript
基于vue如何发布一个npm包的方法步骤
May 15 Javascript
微信小程序scroll-view不能左右滑动问题的解决方法
Jul 09 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的ASP防火墙
2006/10/09 PHP
PHP 5.3.0 安装分析心得
2009/08/07 PHP
PHP对文件进行加锁、解锁实例
2015/01/23 PHP
Yii隐藏URL中index.php的方法
2016/07/12 PHP
php mysql like 实现多关键词搜索的方法
2016/10/29 PHP
老生常谈PHP 文件写入和读取(必看篇)
2017/05/22 PHP
javascript+css 网页每次加载不同样式的实现方法
2009/12/27 Javascript
基于jquery完美拖拽,可返回拖动轨迹
2012/03/29 Javascript
ie下$.getJSON出现问题的解决方法
2014/02/12 Javascript
JavaScript第一篇之实现按钮全选、功能
2016/08/21 Javascript
nodejs搭建本地服务器并访问文件的方法
2017/03/03 NodeJs
js实现扫雷小程序的示例代码
2017/09/27 Javascript
Node.js 中使用 async 函数的方法
2017/11/20 Javascript
vue自定义指令directive实例详解
2018/01/17 Javascript
vue-swiper的使用教程
2018/08/30 Javascript
javascript将非数值转换为数值
2018/09/13 Javascript
jquery多级树形下拉菜单的实例代码
2019/07/09 jQuery
纯异步nodejs文件夹(目录)复制功能
2019/09/03 NodeJs
Nautil 中使用双向数据绑定的实现
2019/10/02 Javascript
JS原型和原型链原理与用法实例详解
2020/02/05 Javascript
[01:03:00]DOTA2上海特级锦标赛A组败者赛 EHOME VS CDEC第一局
2016/02/25 DOTA
[01:33:14]LGD vs VP Supermajor 败者组决赛 BO3 第二场 6.10
2018/07/04 DOTA
基于python(urlparse)模板的使用方法总结
2017/10/13 Python
python实现定时发送qq消息
2019/01/18 Python
Pytorch上下采样函数--interpolate用法
2020/07/07 Python
Python 实现将某一列设置为str类型
2020/07/14 Python
python开发入门——set的使用
2020/09/03 Python
如何基于Django实现上下文章跳转
2020/09/16 Python
HTML5有哪些新特征
2015/12/01 HTML / CSS
美国爆米花工厂:The Popcorn Factory
2019/09/14 全球购物
一篇.NET面试题
2014/09/29 面试题
邹越感恩父母演讲稿
2014/08/28 职场文书
购房公证委托书(2014版)
2014/09/12 职场文书
使用vue-element-admin框架从后端动态获取菜单功能的实现
2021/04/29 Vue.js
Python爬虫框架之Scrapy中Spider的用法
2021/06/28 Python
如何使用SQL Server语句创建表
2022/04/12 SQL Server