• 解决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 
    ......
    

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

  • 相关阅读:
    linux下编译sphinx拓展
    Java为什么使用连接池
    内部类之.this&&.new
    何为代理
    Qt install Phonon
    Gcc简介与常用命令
    Vim的设置和使用——编程者
    QT程序启动界面的使用
    slide from one widget to another
    Hide the common top menu in Ubuntu 12.04
  • 原文地址:https://www.cnblogs.com/flash3d/p/3715600.html
Copyright © 2020-2023  润新知