解决setInterval计时器不准的问题
在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
......
可以看到虽然触发时间并非绝对准确,但由于每次触发都进行及时修正,所以并没有造成误差积累.
解决setInterval计时器不准的问题的更多相关文章
- setInterval计时器延时问题
计时器延时问题 js计时器 使用setTimeout.setInterval函数时,第二个参数的设置的时间间隔t是自该函数(setTimeout(f1,t).setInterval(f1,t))被调用 ...
- setTimeout setInterval 计时器
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式. 返回值:返回一个 ID(数字),可以将这个ID传递给 clearTimeout() 来取消执行. 案例: 点击按钮开始,停止时 ...
- 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?
https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...
- setInterval和setTimeout的区别以及setInterval越来越快问题的解决方法
setInterval()和setTimeout()方法都是js原生的定时方法,当然它们两个的作用也是不同的,并且最近在做上下滚动公告栏的时候,发现了setInterval()非常令人抓狂的问题,那就 ...
- JS window对象取消计时器clearInterval() clearInterval() 方法可取消由 setInterval() 设置的交互时间。
取消计时器clearInterval() clearInterval() 方法可取消由 setInterval() 设置的交互时间. 语法: clearInterval(id_of_setInterv ...
- JS Window对象 计时器setInterval() 在执行时,从载入页面后每隔指定的时间执行代码。
计时器setInterval() 在执行时,从载入页面后每隔指定的时间执行代码. 语法: setInterval(代码,交互时间); 参数说明: 1. 代码:要调用的函数或要执行的代码串. 2. 交互 ...
- 关于setInterval的坑
一道面试题:“setInterval和setTimeout有什么区别” “如果setInterval计时器的回调函数执行完需要5秒,而计时器时间间隔为3秒,那会发生什么?” 验证代码 让程序滞留固定时 ...
- js_计时器之setInterval
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- javascript运动学教程
本文系笔者学习原生javascript动效的笔记.内容基于某非著名培训机构的视频教程.并重新做了归类整理.删除了一些过时的内容.并重做了GIF图,加上了自己的一些分析. 一. 运动学基础 引子:从左到 ...
随机推荐
- usaco 2010年3月银组题解
usaco银组解题报告 一.石子游戏如果把‘O’当作0,‘X’当做1,则N个洞的每一种状态都可以看做是一个N位二进制数.于是,这个问题就变成了求环绕的N位格雷码.幸运的是,这个结构很容易就能够用一个简 ...
- Linux下查看进程打开的文件句柄数和如何修改
修改文件句柄数在Linux下,我们使用ulimit -n 命令可以看到单个进程能够打开的最大文件句柄数量(socket连接也算在里面).系统默认值1024. 对于一般的应用来说(象Apache.系统进 ...
- Hadoop学习3--安装ssh服务
题前语:为什么要安装这个东西呢? 是因为我们要在多台机器之间通信,这个服务就相当于支持这种通信的一个桥梁,打个比喻,相当于windows里,通过远程桌面连接到其他机器. 所以,安装这个服务,的目的是: ...
- 黄聪:Discuz!X/数据库操作方法、DB::table、C::t
函数 功能 DB::table($tablename) 获取正确带前缀的表名,转换数据库句柄, DB::delete($tablename, 条件,条数限制) 删除表中的数据 DB::insert($ ...
- cf 645F Cowslip Collections 组合数学 + 简单数论
http://codeforces.com/contest/645/problem/F F. Cowslip Collections time limit per test 8 seconds mem ...
- 《精通SQL Server 2008》笔记
7.3触发器的使用 7.4游标的使用 8索引/关系图/完整性 9用户管理
- laravel判断HTTP请求是否ajax
if(Request->ajax()){ echo "AJAX"; }else{ echo '普通请求':}
- Linux重置mysql密码(转载)
From:http://hi.baidu.com/mcspring/item/6358ee27afe7e1c8a5275ab7 首先,必须拥有MySQL操作的所有权限: 其次,停止MySQL服务: / ...
- linux free命令(转载)
来源:http://www.cnblogs.com/peida/archive/2012/12/25/2831814.html free命令可以显示Linux系统中空闲的.已用的物理内存及swap内存 ...
- Java中Filter、Servlet、Listener的学习
1.Filter的功能filter功能,它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个reques ...