setInterval计时器不准的问题解决方法_javascript技巧

在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
......

可以看到虽然触发时间并非绝对准确,但由于每次触发都进行及时修正,所以并没有造成误差积累.

时间: 2024-09-19 10:06:01

setInterval计时器不准的问题解决方法_javascript技巧的相关文章

JavaScript汉诺塔问题解决方法_javascript技巧

本文实例讲述了JavaScript汉诺塔问题解决方法.分享给大家供大家参考.具体实现方法如下: <script language="javascript"> var han=function (disc,src,aux,dst){ if(disc>0){ han(disc-1,src,dst,aux); document.writeln("move disc "+disc+" from "+src+" to "

JavaScript中停止执行setInterval和setTimeout事件的方法_javascript技巧

js 代码中执行循环事件时,经常会用到 setInterval 和 setTimeout 这两个方法,关于这两个方法的细节这里不详细讨论了,简要分享下在需要停止循环事件的时候该如何操作. (1)setInterval 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式,停止该方法可使用 clearInterval 方法.具体示例如下: 复制代码 代码如下: <html> <meta http-equiv="Content-Type" content="t

关于innerHTML后丢失动态绑定的EVENT问题解决方法_javascript技巧

用innerHTML取出一段内容后再innerHTML回去,那么原来动态绑定的事件就会丢失,如: html: 复制代码 代码如下: <body><div id='d1'>点击</div></body> script: 复制代码 代码如下: document.getElementById('d1').onclick=function(){alert(1)}; var html=document.body.innerHTML; document.body.inn

jquery ajax应用中iframe自适应高度问题解决方法_javascript技巧

iframe自适应高度本身是很简单的方法,就是在页面加载完成后,重新计算一下高度即可. 代码如下: 复制代码 代码如下: //公共方法:设置iframe的高度以保证全部显示数据//function SetPageHeight() {//    var iframe = getUrlParam('ifname');//    var myiframe = window.parent.document.getElementById(iframe);//     iframeLoaded(myifra

window.location不跳转的问题解决方法_javascript技巧

今天写代码的时候遇到个问题:html里采用onclick事件来实现window.location = url的跳转,在内嵌元素上又加上了href="javascrit:;"的属性.这时这句window.location的跳转失效了.后来上网查了下,想起javascript里面事件是冒泡传递的事,可能是被内嵌的那个href事件给组织了. 解决办法是:在onclick方法里面增加一句return false的语句,让程序强制跳出不继续执行后面的语句.

关于使用 jBox 对话框的提交不能弹出问题解决方法_javascript技巧

jBox 是个不错的对话框组件. 在 ASP.NET Form 中使用 jBox 的时候,在按钮注册的客户端点击事件中,会发现不能弹出对话框问题. 表现为页面一闪就提交了,导致对话框一闪而过,甚至根本看不到.导致模式对话框失败. 首先,按钮会有默认处理,对于普通的 ASP.NET 按钮来说,会导致表单的提交,提交表单导致了页面的刷新.所以,为了不提交表单,就需要阻止按钮默认的行为,这可以通过下面的代码实现. 复制代码 代码如下: function stopDefault( e ) { // Pr

javascript 动态数据下的锚点错位问题解决方法_javascript技巧

复制代码 代码如下: <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>用 Javascript 实现锚点(Anchor)间平滑跳转</title> <script language="javascript"> // 说明 :用 Javascript 实现锚点(Anchor)间平滑跳转 //

js不能跳转到上一页面的问题解决方法_javascript技巧

问题描述:我们有两个页面A和B,当我们从A跳到B后不做作任何让页面回传的操作,用JS:history.go(-1)就可以回到A页面,但是比如我们有Click,Change事件等激发了页面的回传,此时用history.go(-1)就回不到A页面了. 解决的方法:我们要想办法记录到页面回传的次数N,然后用history.go(-n),就可以回到A页面. 在B页面中放一个控件记录其回传的次数,初始值为1 复制代码 代码如下:   <%@ Page Language="C#" AutoE

JS this作用域以及GET传输值过长的问题解决方法_javascript技巧

在开发项目的时候,前端遇到两个比较隐蔽的问题. 问题一.专IE7浏览器,IE URL参数过长问题,引发HTTP Status 122报错 原因:在IE6.8下没有什么问题,但在IE7就不兼容get参数过长,google上说"Don't use the GET method in Ajax Apps, if you can void it, because IE7 craps out with more than 2032 characters in a get string" 解决方法