DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> HTML基礎知識 >> HTML5詳解 >> html5 Web Workers
html5 Web Workers
編輯:HTML5詳解     

雖然在JavaScript中有setInterval和setTimeout函數使javaScript看起來好像使多線程執行,單實際上Javascript使單線程的,一次只能做一件事情(關於JavaScript單線程可以看看setTimeout()和setInterval() 何時被調用執行),看個簡單的例子證明一下

<!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”,事實是只要不關閉對話框,控制台永遠不會輸出文字,這兩句話確實是在一個線程內運行的。

這樣的設計使JavaScript比較簡單,但有時候也很令人煩惱,因為單線程的設計意味著Javascript代碼必須很快運行完,常見的問題就 是一段復雜的JavaScript腳本會中斷頁面其它腳本執行,甚至會出現頁面失去響應,這也就是為什麼AJax的API要設計成異步的。

Web Workers

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

web worker

我們需要把希望單獨執行的Javascript代碼放到一個單獨的JS文件中,然後在頁面中調用Worker構造函數來創建一個線程,參數是該文件 路徑,參數存放如果是相對地址,那麼要以包含調用Worker構造函數語句所在腳本為參照,如果是絕對路徑,需要保證同源(協議+主機+端口)。這個文件 不需要我們在頁面使用script標簽顯示引用

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

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

我們可以看到worker對象只有兩個屬性,其實是兩個回調函數句柄

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

在其prototype內有兩個重要方法

  1. postMessage:很熟悉的趕腳,之前我們介紹過window對象的postMessage()方法,woker的postMessage方法和window的比較類似,但參數略有不同,只需要傳遞消息內容就可以,而且支持所有JavaScript原生數據類型,當然不放心的話同樣也可以序列化為字符串傳遞
  2. terminate:終止worker執行,有些worker執行比較慢,主線程可以主動終止其執行

簡單的小例子

在一個頁面顯示0~10000內所有可以被n整除的數,當然我們不用i*n這種,要略微使計算顯得復雜一些嘛

index.Html

<!DOCTYPE html>
<Html>
<head>
    <title>Web Workers</title>
</head>
<body>
  <h1>Web Workers</h1>

      <div id="test" style="width:500px;"></div>
    <script type="text/Javascript">
        var worker=new Worker('js/worker.JS');
        worker.postMessage({
            n:69
        });

        worker.onmessage=function(e){
            var test=document.getElementById('test').innerHTML=e.data;        
        };
    </script>
</body>
</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,這方面沒有太仔細看,浏覽器兼容性也不討理想,有興趣同學可以上網搜索研究一下。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved