• js基础 ---- 为什么定时器时间不准确


    一、为什么会出现定时器不准确

      这个其实就得提到js执行机制了,叫做事件循环Eventloop 循环机制中,异步事件 setInterval 到时后会把回调函数放入消息队列中Event Queue,主线程的宏任务执行完毕后依次执行消息队列的微任务,等微任务执行完了在循环回来执行宏任务。并且由于消息队列中存在大量任务,其他任务执行时间就会造成定时器回调函数的延迟,如果不处理则会一直叠加延迟

    二、宏任务和微任务

      js可分为同步任务和异步任务,对于同步的任务,我们当然知道按照顺序进行执行,但是对于异步的操作,会有一个优先级的执行顺序,分别为宏任务和微任务

      宏任务:setTimeout, setInterval, setImmediate, I/O, UI rendering

          宏任务是一个外部脚本文件,一个用户交互触发的事件或一个setTimeout调用的回调函数。为了实现单线程这个概念,js有一个宏任务队列(先进先出),宏任务不断地创建出来塞到队尾,js引擎不断地从队首取任务出来执行。

      微任务:process.nextTick, Promises, MutationObserver

          微任务是由Promise创建出来的且js中有一个专门的微任务队列来存储微任务。微任务的机制是:当执行完一个任务后,只要有微任务就先执行微任务。宏任务和渲染通通排到后面。

                                           

     三、解决方法

        根据定时器最开始时间计算当前时间(回调函数执行时间)与开始时间的误差,用期望时差减误差作为下一次任务的时间间隔

          var startTime = new Date().getTime();
          var count = 0;
          //耗时任务
          setInterval(function(){
          var i = 0;
          while(i++ < 100000000);
          }, 0);
          function handle() {
            count++;
            var offset = new Date().getTime() - (startTime + count * 1000);
            var nextTime = 1000 - offset;
            if (nextTime < 0) nextTime = 0;
            setTimeout(handle, nextTime);
            console.log(count + ' --- ' + (new Date().getTime() - (startTime + count * 1000)));
          }
          setTimeout(handle, 1000);

  • 相关阅读:
    03server
    Storm介绍(一)
    storm总结
    Spring源码分析(七)扩展接口BeanPostProcessors源码分析
    技术大牛养成指南
    02装配bean
    02Activity
    maven构建项目
    IDEA使用
    从GIt上导出Maven项目
  • 原文地址:https://www.cnblogs.com/qlb-7/p/13794075.html
Copyright © 2020-2023  润新知