既然javascript在一定時間內(nèi)之執(zhí)行一部分代碼(源于單線程的特性),那么這些代碼塊的每一個就被封鎖在其它異步事件執(zhí)行的進程中。這表明當一個異步事件發(fā)生時(如鼠標點擊、計時器釋放、XMLHttpRequest請求完成),它將排隊等候執(zhí)行(如何排隊在不同瀏覽器之間是不一樣的)。
首先,在第一代碼塊里,有兩個計時器觸發(fā):一個是10ms的setTimeout,一個是10ms的setInterval。在第一個代碼塊真正完成之前,它實際上已經(jīng)釋放了。但是,注意,它不會立即執(zhí)行(由于單線程的問題,它無能為力),相反,為了能在下一個可行的時間得到執(zhí)行,那些延時函數(shù)被編入隊列。
另外,在第一個代碼塊內(nèi),我們看到鼠標點擊出現(xiàn)。與這個異步事件(我們永遠不知道何時執(zhí)行動作,這樣就可以認為它是不同步的)相關(guān)Javascript回調(diào)函數(shù)跟初始的計時器一樣不能立即被執(zhí)行,它排隊等候執(zhí)行。
在Javascript最初的代碼塊執(zhí)行完畢之后,瀏覽器會發(fā)出疑問:正在等候執(zhí)行的是什么?在這種情況下,鼠標點擊處理器和計時器回調(diào)函數(shù)同時處于等待之中,然后,瀏覽器將選擇一個并立即執(zhí)行它,計時器函數(shù)將等到下一個可能的時間執(zhí)行。
注意,當鼠標點擊函數(shù)處理器執(zhí)行時,第一個回調(diào)函數(shù)也在執(zhí)行,至于計時器,其處理器被編入隊列稍后執(zhí)行。但是,請注意,當Interval再次釋放時(在計時器處理器執(zhí)行時),計時器執(zhí)行的時間將減少。如果你在一大塊代碼執(zhí)行期間將所有的Interval回調(diào)函數(shù)編入隊列,其結(jié)果是一大群Interval回調(diào)函數(shù)會毫無延遲的執(zhí)行,直到全部完成。而瀏覽器在隊列增大之前只是簡單的等到?jīng)]有Interval處理器排隊為止(間歇問題)。
事實上,我們看到這樣一個情況:Interval正在執(zhí)行時,第三個Interval函數(shù)將釋放。這表明一個重要的事實:Interval對當前正在執(zhí)行什么漠不關(guān)心,它們將不會青紅皂白的排隊,即使是犧牲回調(diào)函數(shù)之間的時間也在所不辭。
最后,在第二個Interval函數(shù)執(zhí)行完畢之后,我們可以看到?jīng)]有留下任何Javascript引擎執(zhí)行的東西。也就是說,瀏覽器在等待一個新的異步事件的出現(xiàn)。Interval再次釋放時,我們在50ms處獲得它,但這一次,執(zhí)行起來沒有任何障礙,它立即釋放。
我們來看一個例子,以便更好的說明setTimeout和setInterval的差異:
setTimeout(function(){ /* Some long block of code... */ setTimeout(arguments.callee, 10); }, 10); setInterval(function(){ /* Some long block of code... */ }, 10);
乍一看,這兩段代碼似乎功能相同,但并非如此。setTimeout代碼在前一個回調(diào)函數(shù)執(zhí)行萬之后,至少有10ms的延遲(最終可能多些,但至少不會少于此),而setInterval將每隔10ms嘗試執(zhí)行一次回調(diào)函數(shù)而不管最后一個回調(diào)函數(shù)何時執(zhí)行。
這里有很多我們需要了解,讓我們回顧一下:
- Javascript只有單線程,異步事件被迫排隊等候執(zhí)行;
- setTimeout和setInterval在如何執(zhí)行異步代碼方面有根本的區(qū)別;
- 如果計時器無法立即執(zhí)行,它將延時到下一個可能的時間執(zhí)行(這比預想的延遲時間要長一些);
- 如果有充分的執(zhí)行時間,Interval可能會毫無延遲的來回執(zhí)行。
所有這些無疑是重要的知識,了解Javascript引擎如何工作,特別是有大量異步事件出現(xiàn)時,這使得在構(gòu)建高級應用代碼片段時有一個良好的基礎。
出處:
責任編輯:bluehearts
上一頁 解讀javascript的計時器 [1] 下一頁 解讀javascript的計時器 [3]
◎進入論壇網(wǎng)頁制作、WEB標準化版塊參加討論,我還想發(fā)表評論。
|