js 定時器筆記

本文是學習js定時器、單線程、同步異步任務的筆記,只適合初學者。javascript

1、定時器(timer)

JavaScript提供定時執行代碼的功能,該功能主要由setTimeout()和setInterval()這兩個函數來實現html

2、setTimeout()

一、使用規則

setTimeout函數用來指定某個函數或某段代碼,在多少毫秒以後執行。
第一個參數是函數名或者語句,第二個參數延遲的時間參數,單位爲msjava

var timerId = setTimeout(function|code, delay)
setTimeout('console.log(2)',1000);

它返回定時器的編號,之後能夠用來取消這個定時器。ajax

clipboard.png

二、使用注意

推遲執行的代碼必須以字符串的形式,放入setTimeout。
由於引擎內部使用eval函數,將字符串轉爲代碼。
若是推遲執行的是函數,則能夠直接將函數名,放入setTimeout
一方面eval函數有安全顧慮,另外一方面爲了便於JavaScript引擎優化代碼,setTimeout方法通常老是採用函數名的形式安全

clipboard.png

3、setInterval()

setInterval函數的用法與setTimeout徹底一致,區別僅僅在於setInterval指定某個任務每隔一段時間就執行一次。若是不取消的話,就會無限次的定時執行。
第一個參數是函數名或者語句,第二個參數是間隔執行的時間,單位爲ms
例一:實現自增數據輸出服務器

var i=0
var timer=setInterval(function(){console.log(i++)},1000)
//不要在function傳遞i參數,否則獲得的就是NaN

clipboard.png

例二:實現定時器的功能閉包

var timer=setInterval(function(){console.log(new Date)},1000)

clipboard.png

4、解除定時器clearTimeout(),clearInterval()

setTimeout和setInterval函數,都返回一個表示計數器編號的整數值。
將該整數傳入clearTimeout和clearInterval函數,就能夠取消對應的定時器。異步

var id1 = setTimeout(f,1000);
var id2 = setInterval(f,1000);

clearTimeout(id1);
clearInterval(id2);

五:舉個例子
其實這篇文章寫定時器的經典案例寫的很棒JavaScrip同步、異步、回調執行順序之經典閉包setTimeout分析async

var i=0;
for(var i=0; i<10; i++){
  setTimeout(function(){
      console.log(i)
  }, 1000)
}

執行結果:函數

clipboard.png

解析:先執行主線程的for循環,for循環執行了10次,把匿名函數添加了到任務序列10次。等for循環執行完畢,i變成10以後,把任務序列的函數添加到主線程,輸出10次i=10.

var t = true;  
setTimeout(function(){ 
  t = false; 
}, 1000);  

while(t){console.log('end') }

執行結果:不停的輸出end,不會再1000ms以後中止的。
解析:由於while循環是在主線程執行,主線程的while的循環不中止,是不會再執行任務隊列裏面setimeout的函數的。

6、單線程模型

5、6、七章的內容所有來源於 阮一峯JavaScript 標準參考教程(alpha)
單線程模型指的是,JavaScript 只在一個線程上運行。也就是說,JavaScript 同時只能執行一個任務,其餘任務都必須在後面排隊等待。

注意,JavaScript 只在一個線程上運行,不表明 JavaScript 引擎只有一個線程。事實上,JavaScript 引擎有多個線程,單個腳本只能在一個線程上運行(稱爲主線程),其餘線程都是在後臺配合。

7、同步任務和異步任務

5、6、七章的內容所有來源於 阮一峯JavaScript 標準參考教程(alpha)
程序裏面全部的任務,能夠分紅兩類:同步任務(synchronous)和異步任務(asynchronous)。

同步任務是那些沒有被引擎掛起、在主線程上排隊執行的任務。只有前一個任務執行完畢,才能執行後一個任務。

異步任務是那些被引擎放在一邊,不進入主線程、而進入任務隊列的任務。只有引擎認爲某個異步任務能夠執行了(好比 Ajax 操做從服務器獲得告終果),該任務(採用回調函數的形式)纔會進入主線程執行。

8、任務隊列

JavaScript 運行時,除了一個正在運行的主線程,引擎還提供一個任務隊列(task queue),裏面是各類須要當前程序處理的異步任務。

首先,主線程會去執行全部的同步任務。等到同步任務所有執行完,就會去看任務隊列裏面的異步任務。若是知足條件,那麼異步任務就從新進入主線程開始執行,這時它就變成同步任務了。等到執行完,下一個異步任務再進入主線程開始執行。一旦任務隊列清空,程序就結束執行。

引用這一次,完全弄懂 JavaScript 執行機制這篇文章的解析:

同步和異步任務分別進入不一樣的執行"場所",同步的進入主線程,異步的進入Event Table並註冊函數。
當指定的事情完成時,Event Table會將這個函數移入Event Queue。
主線程內的任務執行完畢爲空,會去Event Queue讀取對應的函數,進入主線程執行。
上述過程會不斷重複,也就是常說的Event Loop(事件循環)。

clipboard.png

9、異步與回調函數

來源:若是沒有callback函數,會先執行f2,f3函數再執行f2函數。
可是若是f1,f2函數是有前後順序的,必須f1執行完成,再執行f2的話(f1多是獲取ajax,f2是處理ajax數據),就須要回調函數。

給f1設置callback函數作參數,而後把這個參數當成函數執行,執行f1的過程當中,設置了一個定時器,等數據到來以後,再去執行callback函數。而後把f2做爲f1的參數來調用

function f1(callback){
    setTimeout(function(){
        //作某件事,可能好久
        console.log('別急,開始執行f1')
        for(var i=0;i< 100000;i++){

        }
        console.log('f1執行完了')

        callback()
    }, 0);

}
function f2(){
    console.log('執行f2');
}
function f3(){
    console.log('執行f3');
}
f1(f2) //當f1執行完以後再執行 f2
f3()

十、函數節流

轉載一篇函數節流與函數防抖,寫的很是好,具體內容可看這篇文章。我再也不贅述,我只記錄一下節流的代碼

var timer
  function hiFrequency(){
      if(timer){
          clearTimeout(timer)
      }
        timer = setTimeout(function(){
             console.log('do something')
        }, 300)
  }

  hiFrequency()
  hiFrequency()
  hiFrequency()
相關文章
相關標籤/搜索