html5 Web Workers

雖然在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

Web Workers

在html5規範中引入了web workers概念,解決客戶端JavaScript沒法多線程的問題,其定義的worker是指代碼的並行線程,不過web worker處於一個自包含的環境中,沒法訪問主線程的window對象和document對象,和主線程通訊只能經過異步消息傳遞機制。(《JavaScript權威指南》)java

web worker

咱們須要把但願單獨執行的javascript代碼放到一個單獨的js文件中,而後在頁面中調用Worker構造函數來建立一個線程,參數是該文件路徑,參數存放若是是相對地址,那麼要以包含調用Worker構造函數語句所在腳本爲參照,若是是絕對路徑,須要保證同源(協議+主機+端口)。這個文件不須要咱們在頁面使用script標籤顯示引用web

var worker=new Worker('js/worker.js');

 

這時候這個文件就會被異步加載並在後臺執行,建立成功地worker是醬紫的ajax

咱們能夠看到worker對象只有兩個屬性,實際上是兩個回調函數句柄瀏覽器

  1. onerror:當worker運行出現錯誤,而且沒有在worker中ing捕獲,會在此捕獲
  2. onmessage:當worker向主線程發送消息是調用

在其prototype內有兩個重要方法cookie

  1. postMessage:很熟悉的趕腳,以前咱們介紹過window對象的postMessage()方法,woker的postMessage方法和window的比較相似,但參數略有不一樣,只須要傳遞消息內容就能夠,並且支持全部JavaScript原生數據類型,固然不放心的話一樣也能夠序列化爲字符串傳遞
  2. terminate:終止worker執行,有些worker執行比較慢,主線程能夠主動終止其執行

簡單的小例子

在一個頁面顯示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事件的處理程序會被調用

worker的做用域

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沒有監聽消息,那麼當全部任務執行完畢(包括計數器)後,他就會退出。

web worker中可使用什麼

 前面提到在worker中不能使用window對象和docuemnt對象,那麼可以使用什麼呢

  • JavaScript的全局對象:JSON、Date()、Array
  • self自身引用
  • location對象,可是其屬性都是隻讀的,改了也影響不到調用者
  • navigator對象
  • setTimeout()、setInterval()及其對應清除方法
  • addEventListener()、removeEventListener()

最後

web worker還支持sub worker和共享worker,這方面沒有太仔細看,瀏覽器兼容性也不討理想,有興趣同窗能夠上網搜索研究一下。

相關文章
相關標籤/搜索