setTimeout和setInterval的深入理解
更新時間:2013年11月08日 17:31:27 作者:
以前寫的setTimeout和setInterval的文章有些不足之處,今天抽時間整理了一下,要想真正理解還得從javascript的單線程機(jī)制說起
大概半年前發(fā)表過一篇關(guān)于setTimeout和setInterval的文章,但是現(xiàn)在回去仔細(xì)一看發(fā)現(xiàn)其實存在很多不足以及錯誤。事實上,setTimeout和setInterval并沒有我們字面上理解的那么簡單。要真正掌握并理解這兩個方法,還得從javascript的單線程機(jī)制說起。
【開門見山】setTimeout和setInterval是如何工作的呢?
我們知道,js是單線程執(zhí)行的。所以其實setTimeout和setInterval所謂的“異步調(diào)用”事實上是通過將代碼段插入到代碼的執(zhí)行隊列中實現(xiàn)的。
而如何計算插入的時間點呢?自然是要用到我們所說的timer,也就是計時器。當(dāng)執(zhí)行setTimeout和setInterval的時候,timer會根據(jù)你設(shè)定的時間“準(zhǔn)確”地找到代碼的插入點。當(dāng)隊列“正?!钡貓?zhí)行到插入點時,就觸發(fā)timer callback,也就是我們設(shè)定的回調(diào)函數(shù):
function fn() {
/*
here is some codes
*/
setTimeout(function() {alert('ok!')},1000);
}
上面這個例子就是我們通常的用法,應(yīng)該容易理解。可是,timer真的能那么準(zhǔn)確么?代碼隊列的執(zhí)行真的能那么正常么?
【斬草除根】重新認(rèn)識所謂的“異步”
剛剛已經(jīng)知道,事實上setTimeout和setInterval只是簡簡單單地通過插入代碼到代碼隊列來實現(xiàn)代碼的延遲執(zhí)行(或者說異步執(zhí)行)。但是事實上所謂的異步只是一個假象——它同樣運行在一個線程上!
那么問題就來了,要是在代碼插入點前的代碼執(zhí)行時間超過了傳入setTimeout或setInterval的設(shè)定時間會怎樣呢?讓我們來看看這段代碼:
function fn() {
setTimeout(function(){alert('can you see me?');},1000);
while(true) {}
}
你覺得這段代碼的執(zhí)行結(jié)果是什么呢?答案是,alert永遠(yuǎn)不會出現(xiàn)。
這是為什么呢?因為,while這段代碼沒有執(zhí)行完,插入在后面的代碼便永遠(yuǎn)不會執(zhí)行。
綜上所述,其實JS終歸是單線程產(chǎn)物。無論如何“異步”都不可能突破單線程這個障礙。所以許多的“異步調(diào)用”(包括Ajax)事實上也只是“偽異步”而已。只要理解了這么一個概念,也許理解setTimeout和setInterval也就不難了。
【開門見山】setTimeout和setInterval是如何工作的呢?
我們知道,js是單線程執(zhí)行的。所以其實setTimeout和setInterval所謂的“異步調(diào)用”事實上是通過將代碼段插入到代碼的執(zhí)行隊列中實現(xiàn)的。
而如何計算插入的時間點呢?自然是要用到我們所說的timer,也就是計時器。當(dāng)執(zhí)行setTimeout和setInterval的時候,timer會根據(jù)你設(shè)定的時間“準(zhǔn)確”地找到代碼的插入點。當(dāng)隊列“正?!钡貓?zhí)行到插入點時,就觸發(fā)timer callback,也就是我們設(shè)定的回調(diào)函數(shù):
復(fù)制代碼 代碼如下:
function fn() {
/*
here is some codes
*/
setTimeout(function() {alert('ok!')},1000);
}
上面這個例子就是我們通常的用法,應(yīng)該容易理解。可是,timer真的能那么準(zhǔn)確么?代碼隊列的執(zhí)行真的能那么正常么?
【斬草除根】重新認(rèn)識所謂的“異步”
剛剛已經(jīng)知道,事實上setTimeout和setInterval只是簡簡單單地通過插入代碼到代碼隊列來實現(xiàn)代碼的延遲執(zhí)行(或者說異步執(zhí)行)。但是事實上所謂的異步只是一個假象——它同樣運行在一個線程上!
那么問題就來了,要是在代碼插入點前的代碼執(zhí)行時間超過了傳入setTimeout或setInterval的設(shè)定時間會怎樣呢?讓我們來看看這段代碼:
復(fù)制代碼 代碼如下:
function fn() {
setTimeout(function(){alert('can you see me?');},1000);
while(true) {}
}
你覺得這段代碼的執(zhí)行結(jié)果是什么呢?答案是,alert永遠(yuǎn)不會出現(xiàn)。
這是為什么呢?因為,while這段代碼沒有執(zhí)行完,插入在后面的代碼便永遠(yuǎn)不會執(zhí)行。
綜上所述,其實JS終歸是單線程產(chǎn)物。無論如何“異步”都不可能突破單線程這個障礙。所以許多的“異步調(diào)用”(包括Ajax)事實上也只是“偽異步”而已。只要理解了這么一個概念,也許理解setTimeout和setInterval也就不難了。
您可能感興趣的文章:
- js基于setTimeout與setInterval實現(xiàn)多線程
- 深入理解setTimeout函數(shù)和setInterval函數(shù)
- 快速掌握Node.js中setTimeout和setInterval的使用方法
- JavaScript中setTimeout和setInterval函數(shù)的傳參及調(diào)用
- JavaScript中SetInterval與setTimeout的用法詳解
- javascript中SetInterval與setTimeout的定時器用法
- Javascript中setTimeOut和setInterval的定時器用法
- JavaScript中停止執(zhí)行setInterval和setTimeout事件的方法
- js中的setInterval和setTimeout使用實例
- JavaScript SetInterval與setTimeout使用方法詳解
- BOM系列第二篇之定時器requestAnimationFrame
- BOM系列第三篇之定時器應(yīng)用(時鐘、倒計時、秒表和鬧鐘)
- BOM系列第一篇之定時器setTimeout和setInterval
相關(guān)文章
JavaScript中setFullYear()方法的使用詳解
這篇文章主要介紹了JavaScript中setFullYear()方法的使用詳解,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-06-06JavaScript事件處理器中的event參數(shù)使用介紹
當(dāng)一個事件處理器被觸發(fā)時,名為Event的類實例會作為第一個參數(shù)傳入處理器中,下面為大家詳細(xì)介紹下它的應(yīng)用2013-05-05Mobile Web開發(fā)基礎(chǔ)之四--處理手機(jī)設(shè)備的橫豎屏問題
這篇文章主要介紹了Mobile Web開發(fā)基礎(chǔ)之-—處理手機(jī)設(shè)備的橫豎屏,window.orientation屬性與onorientationchange事件以及media query方式是開發(fā)過程中需要注意到的兩種解決方式,需要的朋友可以參考下2017-08-08Javascript核心讀書有感之詞法結(jié)構(gòu)
這篇文章主要介紹了Javascript核心讀書有感之詞法結(jié)構(gòu),需要的朋友可以參考下2015-02-02Google Dart編程語法和基本類型學(xué)習(xí)教程
Dart編程語言是一個完全面向?qū)ο蟮恼Z言,包括基礎(chǔ)類型如int變量也都是對象,本文主要介紹了Google Dart編程語法和基本類型2013-11-11