WEB Workers

WEB Workers提升WEB前端腳本JavaScript的處理性能 


你有沒有想過在運行大型複雜的JavaScript腳本的時候不會發生瀏覽器假死 

你有沒有想過JavaScript可以在後臺運行? 

你有沒有想過JavaScript函數甚至可以在多個進程中同時運行? 


不可能?當你看完本文,也許會讓你感覺很興奮! 


什麼是Web Workers 

Web WorkersWEB前端網頁上的腳本提供了一種能在後臺進程中運行的方法。一旦它被創建,Web Workers就可以通過postMessage()向任務池發送任務請求,執行完之後再通過postMessage()返回消息給創建者指定的事件處理程序(通過onmessage進行捕獲) 

Web Workers進程能夠在不影響用戶界面的情況下處理任務,並且,它還可以使用XMLHttpRequest來處理I/O,無論responseXMLchannel屬性是否爲null 

注意:通常,後臺進程(包括web workers進程)不能對DOM進行操作。如果希望後臺程序處理的結果能夠改變DOM,只能通過返回消息給創建者的回調函數進行處理。 


瀏覽器支持: 

FireFox3.5(Firefox 3.1 support for DOM workers) 
Safari4 
支持html5的瀏覽器 


進程安全 

Workers接口可以創建真正的系統級別的進程,如果你不小心的話,你的代碼很容易引起併發操作效果,這將會很有趣。 


Mozilla下,Workser併發操作常發生在: 

1、在做網站下載的時候使用Worker 

2、使用Worker實現處理擴展功能。 

創建一個Worker 

我們可以很簡單地創建一個worker,只要調用Worker(URI)構造函數即可。參數URI,要執行的腳本文件地址。 
如果你想獲取worker進程的返回值,可以通過它的onmessage屬性來綁定一個事件處理程序,如: 

var myWorker = new Worker('easyui.js'); 
myWorker.onmessage = function(event){ 
    alert('Called back by the worker!'); 
}; 

第一行用來創建和運行worker進程,第二行設置workeronmessage屬性用來綁定指定的事件處理程序,worker私有的postMessage()方法被調用時,這個被綁定的程序就會被觸發。 


創建一個subworkers 

如果原意,你可以創建多個workerssubworkers必須寄宿於同一個父頁面下,並且,它的URI必須與parent worker的地址同源。這樣可以很好的維持它們的依賴關係。 


Timeouts  intervals 

Workers可以使用timeoutsintervals。這很有用,例如,如果你想讓你的worker進程週期性地運行而不是不停的循環下去的話,你就可以使用了。 

參見:setTimeout(),clearTimeout(),setInterval(),clearInterval() 


終止 worker 

如果你需要馬上終止一個正在運行中的worker,你可以調用它的terminate()方法: 

myWorker.terminate(); 

這樣,一個worker進程就被結束了。 


錯誤捕獲 Handling errors 

worker發生運行時錯誤時,它的onerror事件就會被觸發。該事件接收一個error的事件,該事件不會冒泡,並且可以取消。要取消該事件可以使用preventDefault()方法。 

此錯誤事件有3個屬性: 

message:可讀的錯誤信息 

filename:發生錯誤的腳本文件名稱 

lineno:發生錯誤的腳本所在文件的行數 


訪問navigator對象 

Workers可以訪問navigator對象,它包含下面可以用來標示瀏覽器的字符: 

appName 

appVersion 

platform 

userAgent 


導入腳本和庫 

Worker進程可以訪問全局函數importScripts(),該方法可以將腳本或庫導入到它們的作用域中。 

此方法可以接受空的參數或多個腳本URI參數,下面這些形式都是合法的: 

importScripts();/* imports nothing */ 
importScripts('foo.js');/* import just "foo.js" */ 
importScripts('foo.js','bar.js');/* imports two scripts */ 

Firefox會加載列出的每一個腳本文件,然後運行並初始化。這些腳本中的任何全局對象都可以被worker使用。 

注意:腳本下載可能順序不一樣,但,執行的順序一定是按importScripts中列出的順序進行,而且是同步的,在所有腳本加載完並運行結束後importScripts纔會返回。 


演示 

這部分,我們將演示如何使用DOM Workers. 


在後臺執行指令 

Workers的一個很有用的方法就是使得你的代碼可以在後臺運行,而不影響用戶界面。下面,我們來演示一下使用worker進行Fibonacci數列的計算。 

JavaScript代碼: 

下面的Javascript代碼保存到 fibonacci.js 文件 

JScript code

 

var results = [];

 

var resultReceiver = function(event){

    results.push(parseInt(event.data,10));

    if(results.length==2){

        postMessage(results[0]+results[1]);

    }

};

 

var errorReceiver = function(event){

    throw event.data;

};

 

var onmessage = function(event){

    var n = parseInt(event.data,10);

    if(n==0||n==1){

        postMessage(n);

        return;

    }

    for(var i=0;i<=2;i++){

        var worker = new Worker("fibonacci.js");

        worker.onmessage = resultReceiver;

        worker.onerror = errorReceiver;

        worker.postMessage(n-i);

    }

};

 



onmessage函數在worker調用postMessage()時被觸發,這時便開始遞歸。在裏邊創建新的worker拷貝對每次的計算結果進行迭代。 

HTML代碼 

HTML code

 

<!DOCTYPE HTML PUBLIC "-//W3C/DTD HTML4.0 Transitional//EN">

<html>

<head>

<title>Test threads fibonacci</title>

</head>

<body>

    <div id="result">http://www.v-ec.com/dh20156/article.asp?id=242</div>

    <script type="text/javascript">

        var worker = new Worker("fibonacci.js");

        worker.onmessage = function(event){

            document.getElementById('result').innerHTML = event.data;

            dump('Got:'+event.data+'/n');

        };

        worker.onerror = function(event){

            dump('Worker error:'+error.message+'/n');

            throw error;

        };

        worker.postMessage('5');

    </script>

</body>

</html>

 



在頁面中創建了一個IDresultDIV用來顯示計算結果,然後創建worker,設置onmessage事件用來顯示計算結果到result,設置onerrer事件用來設置dump錯誤信息。 
最後,發送“5”worker,開始計算。 


在後臺操作 WEB I/O 

你可以在此查看到一篇關於Using workers in extensions的文章。 


在多個workers進程中處理任務 

隨着多核計算機的普及,在多進程處理複雜的任務也越來越被更多的人使用,在多個workers進程中處理任務的演示不久將會提供給大家。 


workers中創建workers 

前面Fibonacci例子的演示中我們看到,在workers中可以創建其他的workers,這使得遞歸很容易進行。 


發送對象給workers 

你可以通過postMessage()方法安全地將對象傳遞到workers或者從中返回對象;這些對象將被自動轉換爲JSON格式。 

var onmessage = function(e){ 
    postMessage(e.data); 
}; 

注意:在workers中進出的對象不能包含函數和循環引用,因爲JSON不支持它們。 

See also參見: 

WebWorkers 

Worker 

WorkerGlobalScope 

SharedWorker 

Web Workers specification 

轉載請註明出處:http://www.v-ec.com/dh20156/article.asp?id=242 

經過WEB前端DHTML精英俱樂部測試發現,Safari4已經可以支持Web Workers,不過貌似還不支持在worker中創建worker,所以,本文中上面的Fibonacci例子測試失敗,WEB前端DHTML精英俱樂部重新寫了一個實例進行演示: 
WEB前端專家DHTML精英俱樂部對Web Workers進行的性能測試!

 

 


Firefox 3.5 其中一個最大的特性就是對 worker 的支持(當然safari也支持)workers不僅僅能夠讓我們未來的web APP更加MVC。同時,他的異步後端運算給web程序帶來更多可能性。

到底有什麼好處?來看實例更加直接一些. mozboxPaul Rouget模擬退火算法(Simulated annealing給我們演示了workers的優越性。

 

1. 不瞭解 Simulated annealing 的可以先看看這個圖形化的演示過程,瞭解的同學直接看第二步

http://people.mozilla.com/~prouget/demos/simulatedAnnealing/index.xhtml

load,然後start

 

2. 確定一下,您有沒有安裝firefox 3.5 beta3 

3. 看看worker的演示吧.

http://people.mozilla.com/~prouget/demos/worker_and_simulatedannealing/index.xhtml

 

可以看到如果沒有使用workers,同時計算6Simulated annealing,可以發現瀏覽器已經卡死,gif圖片也停止播放。

當我們開啓workers的演示後,瀏覽器不僅僅沒有卡死,同時gif圖片也正常播放,並且結果的現實比沒有開啓workers前快不少。

 原文地址:

http://blog.mozbox.org/post/2009/04/10/Web-Workers-in-action

發佈了98 篇原創文章 · 獲贊 3 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章