淺談Javascript線程及定時(shí)機(jī)制
setTimeout、setInterval的使用
Javascript api文檔中定義setTimeout和setInterval第二個(gè)參數(shù)意義分別為間隔多少毫秒后回調(diào)函數(shù)被執(zhí)行和每隔多少毫秒回調(diào)函數(shù)被執(zhí)行。但隨著工作經(jīng)驗(yàn)的積累,我們發(fā)現(xiàn)事實(shí)并非如此。
比如
div.onclick=function(){ setTimeout(function(){ document.getElementById('input').focus(); },0); }
就解釋不通了,立即執(zhí)行就立即執(zhí)行唄,干嘛還要設(shè)置個(gè)定時(shí)兜個(gè)圈子呢。
又有一天你寫了下面一段代碼
setTimeout(function(){while(true){}},100); setTimeout(function(){alert('你好');},200);
第一行代碼死循環(huán),結(jié)果造成第二行alert始終沒有出現(xiàn),為啥哩?
單線程or多線程?
原來,Javascript引擎是單線程運(yùn)行的,瀏覽器只有一個(gè)線程在運(yùn)行JavaScript程序。因?yàn)閱尉€程的設(shè)計(jì),所以免去了復(fù)雜的多線程同步問題。
當(dāng)設(shè)置一個(gè)定時(shí)的時(shí)候,瀏覽器會在設(shè)定的時(shí)間后將你指定的回調(diào)函數(shù)插入任務(wù)序列,而非立即執(zhí)行。如果設(shè)定定時(shí)時(shí)間為0,表示立即插入任務(wù)序列,而不是立即執(zhí)行,仍然要等隊(duì)列中任務(wù)執(zhí)行完畢,輪到你,你才執(zhí)行。
所以下面代碼先彈出2,再彈出1
setTimeout(function(){ alert(1); },0); alert(2);
那么,這又有什么實(shí)際用途呢?且看下面示例
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>setTimeout 0</title> </head> <body> 輸入字符,但內(nèi)容卻不能實(shí)時(shí)顯示<input type="text" onkeydown="show(this.value)"/> <br/> 輸入字符,內(nèi)容能實(shí)時(shí)顯示<input type="text" onkeydown="var self=this;setTimeout(function(){show(self.value)},0)"/> <div></div> <script> function show(val){ document.getElementsByTagName("div")[0].innerHTML=val; } </script> </body> </html>
這個(gè)例子中,js引擎需要執(zhí)行keydown事件處理程序,然后更新輸入框的value值。事件處理程序執(zhí)行時(shí),更新value的任務(wù)只能進(jìn)入隊(duì)列等待,所以keydown事件執(zhí)行時(shí)無法得到更新后的value值;但通過setTimeout我們把取value的操作放入隊(duì)列,并在更新value之后執(zhí)行,所以內(nèi)容就能實(shí)時(shí)顯示了。
再回來看看下面的代碼:
setTimeout(function(){ //do something... setTimeout(arguments.callee,10); },10); setInterval(function(){ //do something... },10);
這兩段代碼看起來效果一樣,是不是。其實(shí)還是有區(qū)別的,第一段的回調(diào)函數(shù)內(nèi)的setTimeout是js引擎執(zhí)行后再設(shè)定的新的定時(shí),假定從上一個(gè)回調(diào)處理完到下一個(gè)回調(diào)開始為一個(gè)時(shí)間間隔,理論上時(shí)間間隔>=10ms,后一段代碼<=10ms。
說到這兒,那XMLHttpRequest是不是真的異步呢?是的,請求是異步的,不過這請求是瀏覽器新開的一個(gè)線程。當(dāng)請求的狀態(tài)變更時(shí),如果先前已設(shè)置回調(diào),異步線程就將狀態(tài)變更事件放入js引擎處理隊(duì)列中等待處理,當(dāng)任務(wù)被處理時(shí)js引擎始終還是單線程地執(zhí)行onreadystatechange所設(shè)置的函數(shù)的。
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
相關(guān)文章
微信小程序手機(jī)號驗(yàn)證碼登錄的項(xiàng)目實(shí)現(xiàn)
本文主要介紹了微信小程序手機(jī)號驗(yàn)證碼登錄的項(xiàng)目實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04一個(gè)輕量級的XHTML右鍵菜單[支持IE和firefox]
一個(gè)輕量級的XHTML右鍵菜單[支持IE和firefox]...2007-01-01克隆javascript對象的三個(gè)方法小結(jié)
克隆javascript對象的三個(gè)方法整理,需要的朋友可以參考下。2011-01-01Google AJAX 搜索 API實(shí)現(xiàn)代碼
Google AJAX 搜索 API實(shí)現(xiàn)代碼,需要的朋友可以參考下。2010-11-11javascript中利用柯里化函數(shù)實(shí)現(xiàn)bind方法
這篇文章主要為大家詳細(xì)介紹了javascript中利用柯里化函數(shù)實(shí)現(xiàn)bind方法,感興趣的小伙伴們可以參考一下2016-04-04