• js定时器优化


    在js中如果打算使用setInterval进行倒数,计时等功能,往往是不准确的,因为setInterval的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行.而下一次触发时间则是在setInterval回调函数执行完毕之后才开始计时,所以如果setInterval内执行的计算过于耗时,或者有其他耗时任务在执行,setInterval的计时会越来越不准,延迟很厉害.

    先看以下两看计时器

       setTimeout版

    function test(){
      count += 1;
      console.log(`第${count}次开始 ${getTime.now() - startTime}  ID:${t}`); // 显示开始时间
     
      console.log(`第${count}次结束 ${getTime.now() - startTime}`); // 显示结束时间
      
      //count<1000 && setTimeout(test,500);  //这样写没有ID
      if(count<1000) t=setTimeout(test,500);  //这样写没有ID
    }
     
    let count = -1;
    let getTime = window.performance;
    let startTime = getTime.now();
    var t;
    
    test(); // 300ms间隔

    运行结果

    误差很大,原因js是单线程,而setTimeout两次时间间隔为timer执行时间+interval延时时间,久而久之积累的误差就大了

    setInterval版
    function sleep(time) {
      let startTime = window.performance.now();
      while (window.performance.now() - startTime < time) {}
    }
    
    function test(){
        count++;
        console.log(`第${count}次开始 ${getTime.now() - startTime}`); 
        // 显示开始时间
        //sleep(100); // 程序滞留500ms
        console.log(`第${count}次结束 ${getTime.now() - startTime}`); // 显示结束时间
        count>1000 && clearInterval(t);
    }
    
    let count = 0;
    let getTime = window.performance;
    let startTime = getTime.now();
    
    var t = setInterval(test , 500); // 300ms间隔

    最后结果:

     测了两次结果差很多,可能应该是第一次我切出当前页的原因,已至getTime.now();出错,从第二个结果看,还是很精准的,但是,

    第一种写法:

    1
    2
    3
    4
    funciton xxx(){
    //函数代码,此处执行时间约20毫秒
    setTimeout(xxx,10)
    }

    第二种写法:

    1
    2
    3
    4
    funciton xxx(){
    //函数代码,此处执行时间约20毫秒
    }
    setInterval(xxx,10)

    第一种写法中,只有执行完20ms的代码后,再等10ms才会开始下一个循环;

    第二种写法中,无论有没有执行完20ms的代码,10ms后都会开始下一个循环

    setTimeout优化版:

    var startTime0 = new Date().getTime();
    let count = 0;
    let getTime = window.performance;
    let startTime = getTime.now();
    var t;
    //setTimeout(test,500); // 300ms间隔
    
    setTimeout(function () {
       count += 1;
       console.log(`第${count}次开始 ${getTime.now() - startTime}`); 
       // 显示开始时间
       //sleep(500); // 程序滞留500ms
      
    
       var offset = getTime.now() - (startTime + count * 500);
        var nextTime = 500 - offset;
       //console.log(nextTime);
        if (nextTime < 0) nextTime = 0;
        console.log(`第${count}次结束 ${getTime.now() - startTime}        下次延时:${nextTime}`); // 显示结束时间
        if(count<1000){setTimeout(arguments.callee, nextTime);}
                
      }, 500)

    setTimeout优化后的结果

     setTimeout优化说明:

    1、最大的特点就是动态修正当前触发的延迟时间。

    2、为什么选择setTimeout,因为setTimeout更方便调节延迟时间。

    3、使用performance.now()是当前时间与performance.timing.navigationStart的时间差,以微秒(百万分之一秒)为单位的时间,与 Date.now()-performance.timing.navigationStart的区别是不受系统程序执行阻塞的影响,因此更加精准。关于performance的更多内容 

    4、第二个setTimeout()调用使用了agrument.callee 来获取当前实行函数的引用,并设置另外一个新定时器。这样做可以保证在代码执行完成前不会有新的定时器插入。(来自

    相关链接:https://blog.csdn.net/acm765152844/article/details/51298915

  • 相关阅读:
    201521123028 《Java程序设计》第5周学习总结
    Markdown格式
    201521123028《Java程序设计》第4周学习总结
    201521123028 《Java程序设计》第3周学习总结
    Spring07 JDBC
    Spring06 Aop
    Mystring05 配置文件之间的关系
    Mybatais 13 二级缓存
    Mybatais 14 注释的配置
    Mybatais 12 一级缓存
  • 原文地址:https://www.cnblogs.com/7qin/p/10225220.html
Copyright © 2020-2023  润新知