超碰人人人人人,亚洲AV午夜福利精品一区二区,亚洲欧美综合区丁香五月1区,日韩欧美亚洲系列

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

JavaScript是否可實(shí)現(xiàn)多線程 深入理解JavaScript定時機(jī)制

admin
2010年11月25日 23:38 本文熱度 4149
容易欺騙別人感情的JavaScript定時器
JavaScript的setTimeout與setInterval是兩個很容易欺騙別人感情的方法,因?yàn)槲覀冮_始常常以為調(diào)用了就會按既定的方式執(zhí)行, 我想不少人都深有同感, 例如
 

復(fù)制代碼 代碼如下:
setTimeout( function(){ alert('你好!'); } , 0);
setInterval( callbackFunction , 100);
 

認(rèn)為setTimeout中的問候方法會立即被執(zhí)行,因?yàn)檫@并不是憑空而說,而是JavaScript API文檔明確定義第二個參數(shù)意義為隔多少毫秒后,回調(diào)方法就會被執(zhí)行. 這里設(shè)成0毫秒,理所當(dāng)然就立即被執(zhí)行了.
同理對setInterval的callbackFunction方法每間隔100毫秒就立即被執(zhí)行深信不疑!
但隨著JavaScript應(yīng)用開發(fā)經(jīng)驗(yàn)不斷的增加和豐富,有一天你發(fā)現(xiàn)了一段怪異的代碼而百思不得其解:
 

復(fù)制代碼 代碼如下:
div.onclick = function(){
setTimeout( function(){document.getElementById('inputField').focus();}, 0);
};
 

既然是0毫秒后執(zhí)行,那么還用setTimeout干什么, 此刻, 堅(jiān)定的信念已開始動搖.
直到最后某一天 , 你不小心寫了一段糟糕的代碼:
 

復(fù)制代碼 代碼如下:
setTimeout( function(){ while(true){} } , 100);
setTimeout( function(){ alert('你好!'); } , 200);
setInterval( callbackFunction , 200);
 

第一行代碼進(jìn)入了死循環(huán),但不久你就會發(fā)現(xiàn),第二,第三行并不是預(yù)料中的事情,alert問候未見出現(xiàn),callbacKFunction也杳無音訊!
這時你徹底迷惘了,這種情景是難以接受的,因?yàn)楦淖冮L久以來既定的認(rèn)知去接受新思想的過程是痛苦的,但情事實(shí)擺在眼前,對JavaScript真理的探求并不會因?yàn)橥纯喽V?下面讓我們來展開JavaScript線程和定時器探索之旅!
拔開云霧見月明
出現(xiàn)上面所有誤區(qū)的最主要一個原因是:潛意識中認(rèn)為,JavaScript引擎有多個線程在執(zhí)行,JavaScript的定時器回調(diào)函數(shù)是異步執(zhí)行的.
而事實(shí)上的,JavaScript使用了障眼法,在多數(shù)時候騙過了我們的眼睛,這里背光得澄清一個事實(shí):
JavaScript引擎是單線程運(yùn)行的,瀏覽器無論在什么時候都只且只有一個線程在運(yùn)行JavaScript程序.
JavaScript引擎用單線程運(yùn)行也是有意義的,單線程不必理會線程同步這些復(fù)雜的問題,問題得到簡化.
那么單線程的JavaScript引擎是怎么配合瀏覽器內(nèi)核處理這些定時器和響應(yīng)瀏覽器事件的呢?
下面結(jié)合瀏覽器內(nèi)核處理方式簡單說明.
瀏覽器內(nèi)核實(shí)現(xiàn)允許多個線程異步執(zhí)行,這些線程在內(nèi)核制控下相互配合以保持同步.假如某一瀏覽器內(nèi)核的實(shí)現(xiàn)至少有三個常駐線程:javascript引擎線程,界面渲染線程,瀏覽器事件觸發(fā)線程,除些以外,也有一些執(zhí)行完就終止的線程,如Http請求線程,這些異步線程都會產(chǎn)生不同的異步事件,下面通過一個圖來闡明單線程的JavaScript引擎與另外那些線程是怎樣互動通信的.雖然每個瀏覽器內(nèi)核實(shí)現(xiàn)細(xì)節(jié)不同,但這其中的調(diào)用原理都是大同小異.

由圖可看出,瀏覽器中的JavaScript引擎是基于事件驅(qū)動的,這里的事件可看作是瀏覽器派給它的各種任務(wù),這些任務(wù)可以源自 JavaScript引擎當(dāng)前執(zhí)行的代碼塊,如調(diào)用setTimeout添加一個任務(wù),也可來自瀏覽器內(nèi)核的其它線程,如界面元素鼠標(biāo)點(diǎn)擊事件,定時觸發(fā)器時間到達(dá)通知,異步請求狀態(tài)變更通知等.從代碼角度看來任務(wù)實(shí)體就是各種回調(diào)函數(shù),JavaScript引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來.由于單線程關(guān)系,這些任務(wù)得進(jìn)行排隊(duì),一個接著一個被引擎處理.
上圖t1-t2..tn表示不同的時間點(diǎn),tn下面對應(yīng)的小方塊代表該時間點(diǎn)的任務(wù),假設(shè)現(xiàn)在是t1時刻,引擎運(yùn)行在t1對應(yīng)的任務(wù)方塊代碼內(nèi),在這個時間點(diǎn)內(nèi),我們來描述一下瀏覽器內(nèi)核其它線程的狀態(tài).
t1時刻:
GUI渲染線程:

該線程負(fù)責(zé)渲染瀏覽器界面HTML元素,當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時,該線程就會執(zhí)行.本文雖然重點(diǎn)解釋JavaScript定時機(jī)制,但這時有必要說說渲染線程,因?yàn)樵摼€程與JavaScript引擎線程是互斥的,這容易理解,因?yàn)?JavaScript腳本是可操縱DOM元素,在修改這些元素屬性同時渲染界面,那么渲染線程前后獲得的元素?cái)?shù)據(jù)就可能不一致了.
在JavaScript引擎運(yùn)行腳本期間,瀏覽器渲染線程都是處于掛起狀態(tài)的,也就是說被”凍結(jié)”了.
所以,在腳本中執(zhí)行對界面進(jìn)行更新操作,如添加結(jié)點(diǎn),刪除結(jié)點(diǎn)或改變結(jié)點(diǎn)的外觀等更新并不會立即體現(xiàn)出來,這些操作將保存在一個隊(duì)列中,待 JavaScript引擎空閑時才有機(jī)會渲染出來.或許這里你有個疑問了,為什么JS代碼塊的alert時界面有更新的,JS不是正在運(yùn)行嗎?其實(shí)當(dāng) alert發(fā)生時,瀏覽器內(nèi)核就會掛起JavaScript引擎線程,并促使界面執(zhí)行了更新.
GUI事件觸發(fā)線程:
JavaScript腳本的執(zhí)行不影響html元素事件的觸發(fā),在t1時間段內(nèi),首先是用戶點(diǎn)擊了一個鼠標(biāo)鍵,點(diǎn)擊被瀏覽器事件觸發(fā)線程捕捉后形成一個鼠標(biāo)點(diǎn)擊事件,由圖可知,對于JavaScript引擎線程來說,這事件是由其它線程異步傳到任務(wù)隊(duì)列尾的,由于引擎正在處理t1時的任務(wù),這個鼠標(biāo)點(diǎn)擊事件正在等待處理.
定時觸發(fā)線程:
注意這里的瀏覽器模型定時計(jì)數(shù)器并不是由JavaScript引擎計(jì)數(shù)的,因?yàn)镴avaScript引擎是單線程的,如果處于阻塞線程狀態(tài)就計(jì)不了時,它必須依賴外部來計(jì)時并觸發(fā)定時,所以隊(duì)列中的定時事件也是異步事件.
由圖可知,在這t1的時間段內(nèi),繼鼠標(biāo)點(diǎn)擊事件觸發(fā)后,先前已設(shè)置的setTimeout定時也到達(dá)了,此刻對JavaScript引擎來說,定時觸發(fā)線程產(chǎn)生了一個異步定時事件并放到任務(wù)隊(duì)列中, 該事件被排到點(diǎn)擊事件回調(diào)之后,等待處理.
同理, 還是在t1時間段內(nèi),接下來某個setInterval定時器也被添加了,由于是間隔定時,在t1段內(nèi)連續(xù)被觸發(fā)了兩次,這兩個事件被排到隊(duì)尾等待處理.
可見,假如時間段t1非常長,遠(yuǎn)大于setInterval的定時間隔,那么定時觸發(fā)線程就會源源不斷的產(chǎn)生異步定時事件并放到任務(wù)隊(duì)列尾而不管它們是否已被處理,但一旦t1和最先的定時事件前面的任務(wù)已處理完,這些排列中的定時事件就依次不間斷的被執(zhí)行,這是因?yàn)?對于JavaScript引擎來說,在處理隊(duì)列中的各任務(wù)處理方式都是一樣的,只是處理的次序不同而已.
t1過后,也就是說當(dāng)前處理的任務(wù)已返回,JavaScript引擎會檢查任務(wù)隊(duì)列,發(fā)現(xiàn)當(dāng)前隊(duì)列非空,就取出t2下面對應(yīng)的任務(wù)執(zhí)行,其它時間依此類推,由此看來:
如果隊(duì)列非空,引擎就從隊(duì)列頭取出一個任務(wù),直到該任務(wù)處理完,即返回后引擎接著運(yùn)行下一個任務(wù),在任務(wù)沒返回前隊(duì)列中的其它任務(wù)是沒法被執(zhí)行的.
可以試試運(yùn)行以下例子作測試,第一個定時器是一個死循環(huán),第二個定時器是向界面輸出一串字符串,第一個定時器比第二個定時器要來得早.
 

復(fù)制代碼 代碼如下:
setTimeout(function(){
for(;;);
}, 50);
setTimeout(function(){alert('Hello');}, 51);
 

運(yùn)行后可看出,在沒瀏覽器沒提示腳本繁忙前第二個定時器alert是不會彈出的,因?yàn)閱尉€程關(guān)系,第一個定時器回調(diào)腳本未返回前第二個腳本是沒機(jī)會運(yùn)行.
相信您現(xiàn)在已經(jīng)很清楚JavaScript是否可多線程,也了解理解JavaScript定時器運(yùn)行機(jī)制了,下面我們來對一些案例進(jìn)行分析:
案例1:setTimeout與setInterval
 

復(fù)制代碼 代碼如下:
setTimeout(function(){
/* 代碼塊... */
setTimeout(arguments.callee, 10);
}, 10);
setInterval(function(){
/*代碼塊... */
}, 10);
 

這兩段代碼看一起效果一樣,其實(shí)非也,第一段中回調(diào)函數(shù)內(nèi)的setTimeout是JavaScript引擎執(zhí)行后再設(shè)置新的setTimeout 定時, 假定上一個回調(diào)處理完到下一個回調(diào)開始處理為一個時間間隔,理論兩個setTimeout回調(diào)執(zhí)行時間間隔>=10ms .第二段自setInterval設(shè)置定時后,定時觸發(fā)線程就會源源不斷的每隔十秒產(chǎn)生異步定時事件并放到任務(wù)隊(duì)列尾,理論上兩個setInterval 回調(diào)執(zhí)行時間間隔<=10.
案例2:ajax異步請求是否真的異步?
很多同學(xué)朋友搞不清楚,既然說JavaScript是單線程運(yùn)行的,那么XMLHttpRequest在連接后是否真的異步?
其實(shí)請求確實(shí)是異步的,不過這請求是由瀏覽器新開一個線程請求(參見上圖),當(dāng)請求的狀態(tài)變更時,如果先前已設(shè)置回調(diào),這異步線程就產(chǎn)生狀態(tài)變更事件放到 JavaScript引擎的處理隊(duì)列中等待處理,當(dāng)任務(wù)被處理時,JavaScript引擎始終是單線程運(yùn)行回調(diào)函數(shù),具體點(diǎn)即還是單線程運(yùn)行 onreadystatechange所設(shè)置的函數(shù).

該文章在 2010/11/25 23:38:31 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved