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 相关文章推荐
jQuery简单验证上传文件大小及类型的方法
Jun 02 Javascript
javascript iframe跨域详解
Oct 26 Javascript
jQuery操作css样式
May 15 jQuery
vue使用keep-alive实现数据缓存不刷新
Oct 21 Javascript
js中let和var定义变量的区别
Feb 08 Javascript
JavaScript中使用import 和require打包后实现原理分析
Mar 07 Javascript
JS实现导出Excel的五种方法详解【附源码下载】
Mar 15 Javascript
利用Console来Debug的10个高级技巧汇总
Mar 26 Javascript
js防抖和节流的深入讲解
Dec 06 Javascript
js prototype和__proto__的关系是什么
Aug 23 Javascript
vue-cli3单页构建大型项目方案
Apr 07 Javascript
JavaScript, select标签元素左右移动功能实现
May 14 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
PHP4在WinXP下IIS和Apache2服务器上的安装实例
2006/10/09 PHP
ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单
2014/05/15 PHP
PHP实现求解最长公共子串问题的方法
2017/11/17 PHP
理解JavaScript中的事件
2006/09/23 Javascript
List the Stored Procedures in a SQL Server database
2007/06/20 Javascript
Prototype String对象 学习
2009/07/19 Javascript
javascript Keycode对照表
2009/10/24 Javascript
理解Javascript_03_javascript全局观
2010/10/11 Javascript
js将控件隐藏及display属性的使用介绍
2013/12/30 Javascript
JavaScript Serializer序列化时间处理示例
2014/07/31 Javascript
javascript中setInterval的用法
2015/07/19 Javascript
Javascript函数式编程简单介绍
2015/10/11 Javascript
jquery彩色投票进度条简单实例演示
2020/07/23 Javascript
JS实现简单易用的手机端浮动窗口显示效果
2016/09/07 Javascript
jQuery zTree树插件动态加载实例代码
2017/05/11 jQuery
webpack进阶——缓存与独立打包的用法
2017/08/02 Javascript
10行原生JS实现文字无缝滚动(超简单)
2018/01/02 Javascript
详解关于表格合并span-method方法的补充(表格数据由后台动态返回)
2019/05/21 Javascript
layer弹出层显示在top顶层的方法
2019/09/11 Javascript
Vue3.0 响应式系统源码逐行分析讲解
2019/10/14 Javascript
浅谈React中组件逻辑复用的那些事儿
2020/05/21 Javascript
浅析JavaScript预编译和暗示全局变量
2020/09/03 Javascript
JavaScript 中的六种循环方法
2021/01/06 Javascript
python教程之用py2exe将PY文件转成EXE文件
2014/06/12 Python
python利用socketserver实现并发套接字功能
2018/01/26 Python
详解pyenv下使用python matplotlib模块的问题解决
2018/11/29 Python
解决项目pycharm能运行,在终端却无法运行的问题
2019/01/19 Python
python numpy生成等差数列、等比数列的实例
2020/02/25 Python
PythonPC客户端自动化实现原理(pywinauto)
2020/05/28 Python
python xlsxwriter模块的使用
2020/12/24 Python
The Hut英国:英国领先的豪华在线百货商店
2019/07/26 全球购物
初中三好学生自我鉴定
2014/04/07 职场文书
员工加薪申请报告
2015/05/15 职场文书
唱歌比赛拉拉队口号
2015/12/25 职场文书
golang内置函数len的小技巧
2021/07/25 Golang
基于Redis结合SpringBoot的秒杀案例详解
2021/10/05 Redis