JavaScript的setTimeout和setInterval的深刻理解

發表過一片博客《跟着我用JavaScript寫計時器》,比較基礎.....有網友說應該寫一下setTimeout的原理和機制,嗯,今天就來寫一下吧:javascript

直奔主題:setTimeout和setInterval是如何工做的呢?

咱們知道,js是單線程執行的(單線程j就是說在程序執行時,所走的程序路徑按照連續順序排下來,前面的必須處理好,後面的纔會執行)。因此其實setTimeout和setInterval所謂的「異步調用」事實上是經過將代碼段插入到代碼的執行隊列中實現的。
而如何計算插入的時間點呢?天然是要用到咱們所說的timer,也就是計時器。當執行setTimeout和setInterval的時候,timer會根據你設定的時間「準確」地找到代碼的插入點。當隊列「正常」地執行到插入點時,就觸發timer callback,也就是咱們設定的回調函數:java

function fn() { 
/* 
here is some codes 
*/ alert("javascript");
setTimeout(function() {alert('ok!')},1000); 
} 
onload=fn;

上面這個例子就是咱們一般的用法,應該容易理解。但是,timer真的能那麼準確麼?代碼隊列的執行真的能那麼正常麼?瀏覽器

還記得嗎?從新認識所謂的「異步」

剛剛已經知道,事實上setTimeout和setInterval只是簡簡單單地經過插入代碼到代碼隊列來實現代碼的延遲執行(或者說異步執行)。可是事實上所謂的異步只是一個假象——它一樣運行在一個線程上! 始終是單線程!
那麼問題就來了,要是在代碼插入點前的代碼執行時間超過了傳入setTimeout或setInterval的設定時間會怎樣呢?讓咱們來看看這段代碼:異步

function fn() { 
setTimeout(function(){alert('can you see me?');},1000); 
while(true) {} 
}

你以爲這段代碼的執行結果是什麼呢?答案是,alert永遠不會出現。
單線程
這是爲何呢?由於,while這段代碼沒有執行完(如圖,瀏覽器一直在解析while的代碼),因此插入在後面的代碼便永遠不會執行。
綜上所述,其實JS終歸是單線程產物。不管如何「異步」都不可能突破單線程這個障礙。因此許多的「異步調用」(包括Ajax)事實上也只是「僞異步」而已。只要理解了這麼一個概念,也許理解setTimeout和setInterval也就不難了。函數

相關文章
相關標籤/搜索