本文是學習js定時器、單線程、同步異步任務的筆記,只適合初學者。javascript
JavaScript提供定時執行代碼的功能,該功能主要由setTimeout()和setInterval()這兩個函數來實現html
setTimeout函數用來指定某個函數或某段代碼,在多少毫秒以後執行。
第一個參數是函數名或者語句,第二個參數延遲的時間參數,單位爲msjava
var timerId = setTimeout(function|code, delay) setTimeout('console.log(2)',1000);
它返回定時器的編號,之後能夠用來取消這個定時器。ajax
推遲執行的代碼必須以字符串的形式,放入setTimeout。
由於引擎內部使用eval函數,將字符串轉爲代碼。
若是推遲執行的是函數,則能夠直接將函數名,放入setTimeout。
一方面eval函數有安全顧慮,另外一方面爲了便於JavaScript引擎優化代碼,setTimeout方法通常老是採用函數名的形式安全
setInterval函數的用法與setTimeout徹底一致,區別僅僅在於setInterval指定某個任務每隔一段時間就執行一次。若是不取消的話,就會無限次的定時執行。
第一個參數是函數名或者語句,第二個參數是間隔執行的時間,單位爲ms
例一:實現自增數據輸出服務器
var i=0 var timer=setInterval(function(){console.log(i++)},1000) //不要在function傳遞i參數,否則獲得的就是NaN
例二:實現定時器的功能閉包
var timer=setInterval(function(){console.log(new Date)},1000)
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) }
執行結果:函數
解析:先執行主線程的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的函數的。
5、6、七章的內容所有來源於 阮一峯JavaScript 標準參考教程(alpha)
單線程模型指的是,JavaScript 只在一個線程上運行。也就是說,JavaScript 同時只能執行一個任務,其餘任務都必須在後面排隊等待。
注意,JavaScript 只在一個線程上運行,不表明 JavaScript 引擎只有一個線程。事實上,JavaScript 引擎有多個線程,單個腳本只能在一個線程上運行(稱爲主線程),其餘線程都是在後臺配合。
5、6、七章的內容所有來源於 阮一峯JavaScript 標準參考教程(alpha)
程序裏面全部的任務,能夠分紅兩類:同步任務(synchronous)和異步任務(asynchronous)。
同步任務是那些沒有被引擎掛起、在主線程上排隊執行的任務。只有前一個任務執行完畢,才能執行後一個任務。
異步任務是那些被引擎放在一邊,不進入主線程、而進入任務隊列的任務。只有引擎認爲某個異步任務能夠執行了(好比 Ajax 操做從服務器獲得告終果),該任務(採用回調函數的形式)纔會進入主線程執行。
JavaScript 運行時,除了一個正在運行的主線程,引擎還提供一個任務隊列(task queue),裏面是各類須要當前程序處理的異步任務。
首先,主線程會去執行全部的同步任務。等到同步任務所有執行完,就會去看任務隊列裏面的異步任務。若是知足條件,那麼異步任務就從新進入主線程開始執行,這時它就變成同步任務了。等到執行完,下一個異步任務再進入主線程開始執行。一旦任務隊列清空,程序就結束執行。
引用這一次,完全弄懂 JavaScript 執行機制這篇文章的解析:
同步和異步任務分別進入不一樣的執行"場所",同步的進入主線程,異步的進入Event Table並註冊函數。
當指定的事情完成時,Event Table會將這個函數移入Event Queue。
主線程內的任務執行完畢爲空,會去Event Queue讀取對應的函數,進入主線程執行。
上述過程會不斷重複,也就是常說的Event Loop(事件循環)。
來源:若是沒有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()