「JavaScript 定时器」setInterval、setTimeout和requestAnimationFrame浅析

一.常见定时器

咱们常见的定时器有如下两种

1. window.setTimeout 用于在指定的毫秒数后执行某段既定的代码
2. window.setInterval 用于每隔一段毫秒数重复执行既定的代码

这两个方法均可以经过手工设置时间来设定是多少毫秒后执行这段代码,或者是每隔多少毫秒执行这段代码。

虽然咱们期待浏览器按照咱们设定的时间精确的执行代码,可是js却不能保证代码能刚好在那个时间点被运行,缘由有两个。html

  • 大多数浏览器并无精确到毫秒级别的触发事件,例如,咱们设定某个函数在3毫秒后执行,在老版本的IE中,这个函数至少会在15毫秒之后执行。而在现代浏览器中,这个数值会短一点,但时间差通常也会超过1毫秒。
  • 第二个缘由与js的运行机制有关,具体见JavaScript 运行机制详解:再谈Event Loop.简单来讲,就是js是一个单线程的解释器,一段时间只能执行一段代码,因此运行时分为主线程和任务队列两部分。而咱们在定时器中设置的时间,仅表明1000毫秒后把这个任务插入到任务队列中,而此时必需要等到主线程的代码执行完毕,才能执行任务队列中的定时器的任务(在任务队列中也有调度,不必定第一个执行当前任务),所以时间是没法保证的。

2、requestAnimationFrame

那有没有时间准确的定时器呢?有一种选择是requestAnimationFrame. 示例以下:api

function animateMe(){
    requestAnimationFrame(function(){
      console.log(new Date());
      animateMe();
    })
}
animateMe();

这个api的原理是在由系统来决定回调函数的执行时机,在每一次系统绘制以前,会主动调用requestAnimationFrame中的回调函数,而频率也牢牢跟随浏览器的刷新频率。好比通常电脑的刷新频率一般为60Hz,即一秒钟重绘60次,那么回调函数就等于1000/60=16.7毫秒被执行一次,而若是刷新频率变为75Hz,那么这个时间就变为1000/75=13.3毫秒被执行一次。这样能保证回调函数在每一次绘制的间隔时间内只被执行一次,所以它的时间是可靠的。浏览器

3、实战

光说不练假把式,如今咱们就用上面介绍的三种定时器完成进度条的效果。 函数

1.setIntervaloop

var timer;
$('.runBtn').click(function(){
    clearInterval(timer);
    $('#bar').width(0);
    timer = setInterval(function(){
      if($('#bar').width() < 500){
         $('#bar').width($('#bar').width()+5);
         $('#bar').text($('#bar').width()/5+'%');
      }else{
        clearInterval(timer);
      } 
    },16);
 });

点此预览效果学习

2.setTimeout.net

var timer;
$('.runBtn').click(function(){
    clearTimeout(timer);
    $('#bar').width(0);
    timer = setTimeout(function fn(){
      if($('#bar').width() < 500){
         $('#bar').width($('#bar').width()+5);
         $('#bar').text($('#bar').width()/5+'%');
         timer = setTimeout(fn,16);
      }else{
        clearTimeout(timer);
      } 
    },16);
 });

点此预览效果线程

3.requestAnimationFramecode

var timer;
$('.runBtn').click(function(){
    cancelAnimationFrame(timer);
    $('#bar').width(0);
    timer = requestAnimationFrame(function fn(){
      if($('#bar').width() < 500){
         $('#bar').width($('#bar').width()+5);
         $('#bar').text($('#bar').width()/5+'%');
         requestAnimationFrame(fn);
      }else{
        cancelAnimationFrame(timer);
      } 
    });
 });

点此预览效果htm

4、最后

文章都来自本人的总结,不免有些纰漏,欢迎你们指正。一块儿学习,一块儿进步。若是以为不错,欢迎点赞收藏嘤嘤嘤~~~

相关文章
相关标签/搜索