雖然在JavaScript中有setInterval和setTimeout函數使javaScript看起來好像使多線程執行,單實際上JavaScript使單線程的,一次只能作一件事情(關於JavaScript單線程能夠看看setTimeout()和setInterval() 什麼時候被調用執行),看個簡單的例子證實一下javascript
<!DOCTYPE html> <html> <head> <title>Web Workers</title> </head> <body> <h1>Web Workers</h1> <script type="text/javascript"> setTimeout(function(){ console.log('timeout function'); },1000); alert('do not close'); </script> </body> </html>
頁面一運行就會彈出一個對話框,若是setTimeout是在另一個線程運行,那麼過一秒鐘控制檯就會打印「timeout function」,事實是隻要不關閉對話框,控制檯永遠不會輸出文字,這兩句話確實是在一個線程內運行的。html
這樣的設計使JavaScript比較簡單,但有時候也很使人煩惱,由於單線程的設計意味着JavaScript代碼必須很快運行完,常見的問題就是一段複雜的JavaScript腳本會中斷頁面其它腳本執行,甚至會出現頁面失去響應,這也就是爲何ajax的API要設計成異步的。html5
在html5規範中引入了web workers概念,解決客戶端JavaScript沒法多線程的問題,其定義的worker是指代碼的並行線程,不過web worker處於一個自包含的環境中,沒法訪問主線程的window對象和document對象,和主線程通訊只能經過異步消息傳遞機制。(《JavaScript權威指南》)java
咱們須要把但願單獨執行的javascript代碼放到一個單獨的js文件中,而後在頁面中調用Worker構造函數來建立一個線程,參數是該文件路徑,參數存放若是是相對地址,那麼要以包含調用Worker構造函數語句所在腳本爲參照,若是是絕對路徑,須要保證同源(協議+主機+端口)。這個文件不須要咱們在頁面使用script標籤顯示引用web
var worker=new Worker('js/worker.js');
這時候這個文件就會被異步加載並在後臺執行,建立成功地worker是醬紫的ajax
咱們能夠看到worker對象只有兩個屬性,實際上是兩個回調函數句柄瀏覽器
在其prototype內有兩個重要方法cookie
在一個頁面顯示0~10000內全部能夠被n整除的數,固然咱們不用i*n這種,要略微使計算顯得複雜一些嘛多線程
index.html異步
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Web Workers</title> 5 </head> 6 <body> 7 <h1>Web Workers</h1> 8 9 <div id="test" style="width:500px;"></div> 10 <script type="text/javascript"> 11 var worker=new Worker('js/worker.js'); 12 worker.postMessage({ 13 n:69 14 }); 15 16 worker.onmessage=function(e){ 17 var test=document.getElementById('test').innerHTML=e.data; 18 }; 19 </script> 20 </body> 21 </html>
/js/worker.js
function calc(n){ var result=[]; for(var i=1;i<10000;i++){ var tem=i; if(i%n==0){ if(i%(10*n)==0){ tem+='<br/>'; } result.push(tem); } } self.postMessage(result.join(' ')); self.close(); } onmessage=function(e){ calc(e.data.n); };
worker.onmessage
綁定主線程的message事件,當worker調用postMessage時方法時,綁定的事件處理程序會被調用到,傳遞來的數據可使用MouseEvent的data屬性獲取,經過target屬性還能夠獲取worker對象
self是什麼
self是woker中對自身的引用,有些像this
close()
在worker內部調用close()方法效果和在外部調用worker實例的terminate()方法效果同樣,終止worker運行
onmessage
在這個句柄內接收外部調用者傳遞的參數,參數能夠經過e.data獲取
self.postMessage()
沒錯經過這個方法咱們能夠在worker內把結果傳遞給主線程,主線程上綁定的message事件的處理程序會被調用
web worker的簡單用法就是這樣,但有些姿式仍是得了解一下。
全新的JavaScript環境
當一個Worker實例被建立的時候,它會在一個全新的JavaScript運行環境中,徹底和建立worker的腳本分離開,即便咱們傳遞的消息是引用類型它們也是複製傳遞的,修改worker中的參數不影響建立腳本中的參數。
importScripts()
咱們能夠經過importScripts()方法經過url在worker中加載庫函數,
importScripts('utility/dialog.js','common/cookie.js');
方法能夠接受多個url,相對地址的url以當前worker爲參照,方法會按照參數順序依次下載運行庫函數,若是中間某個腳本出錯,剩下的都不會被載入和執行,並且這個方法是同步的,只有全部腳本都加載、運行完後纔會返回。
worker執行模型
worker線程從上到下同步運行它的代碼,而後進入異步階段來對事件及計時器響應,若是worker註冊了message事件處理程序,只要其有可能觸發,worker就一直在內存中,不會退出,但若是worker沒有監聽消息,那麼當全部任務執行完畢(包括計數器)後,他就會退出。
前面提到在worker中不能使用window對象和docuemnt對象,那麼可以使用什麼呢
web worker還支持sub worker和共享worker,這方面沒有太仔細看,瀏覽器兼容性也不討理想,有興趣同窗能夠上網搜索研究一下。