「JavaScript 定時器」setInterval、setTimeout和requestAnimationFrame淺析

一.罕見定時器

我們罕見的定時器有以下兩種

1. window.setTimeout 用於在指定的毫秒數后實行某段既定的代碼
2. window.setInterval 用於每隔一段毫秒數反覆實行既定的代碼

這兩個要領都可以經由過程手工設置時候來設定是若干毫秒后實行這段代碼,或者是每隔若干毫秒實行這段代碼。  

雖然我們期待瀏覽器根據我們設定的時候正確的實行代碼,然則js卻不能保證代碼能正好在誰人時候點被運轉,緣由有兩個。

  • 大多數瀏覽器並沒有正確到毫秒級別的觸發事宜,比方,我們設定某個函數在3毫秒后實行,在老版本的IE中,這個函數最少會在15毫秒今後實行。而在當代瀏覽器中,這個數值會短一點,但時候差平常也會凌駕1毫秒。
  • 第二個緣由與js的運轉機制有關,詳細見JavaScript 運轉機制詳解:再談Event Loop.簡樸來講,就是js是一個單線程的詮釋器,一段時候只能實行一段代碼,所以運轉時分為主線程和使命行列兩部分。而我們在定時器中設置的時候,僅代表1000毫秒后把這個使命插進去到使命行列中,而此時必需要比及主線程的代碼實行終了,才實行使命行列中的定時器的使命(在使命行列中也有調理,不一定第一個實行當前使命),因而時候是沒法保證的。

二、requestAnimationFrame

那有沒有時候正確的定時器呢?有一種挑選是requestAnimationFrame. 示比方下:

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

這個api的道理是在由體系來決議回調函數的實行機遇,在每一次體系繪製之前,會主動挪用requestAnimationFrame中的回調函數,而頻次也牢牢追隨瀏覽器的革新頻次。比方平常電腦的革新頻次一般為60Hz,即一秒鐘重繪60次,那末回調函數就即是1000/60=16.7毫秒被實行一次,而假如革新頻次變成75Hz,那末這個時候就變成1000/75=13.3毫秒被實行一次。如許能保證回調函數在每一次繪製的距離時候內只被實行一次,因而它的時候是牢靠的。

三、實戰

言而不行假把式,如今我們就用上面引見的三種定時器完成進度條的結果。

1.setInterval

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

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

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);
      } 
    });
 });

點此預覽結果

四、末了

文章都來自本人的總結,不免有些馬虎,迎接人人斧正。一同進修,一同提高。假如以為不錯,迎接點贊珍藏嚶嚶嚶~~~

    原文作者:Jchermy
    原文地址: https://segmentfault.com/a/1190000014661035
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞