WEB Workers提高WEB前端腳本JavaScript的處理性能
你有沒有想過在運行大型複雜的JavaScript腳本的時候不會發生瀏覽器假死?
你有沒有想過JavaScript能夠在後臺運行?
你有沒有想過JavaScript函數甚至能夠在多個進程中同時運行?
不可能?當你看完本文,也許會讓你感受很興奮!
什麼是Web Workers?
Web Workers爲WEB前端網頁上的腳本提供了一種能在後臺進程中運行的方法。一旦它被建立,Web Workers就能夠經過postMessage()向任務池發送任務請求,執行完以後再經過postMessage()返回消息給建立者指定的事件處理程序(經過onmessage進行捕獲)。
Web Workers進程可以在不影響用戶界面的狀況下處理任務,而且,它還可使用XMLHttpRequest來處理I/O,不管responseXML和channel屬性是否爲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進程,第二行設置worker的onmessage屬性用來綁定指定的事件處理程序,當worker私有的postMessage()方法被調用時,這個被綁定的程序就會被觸發。
建立一個subworkers
若是原意,你能夠建立多個workers。subworkers必須寄宿於同一個父頁面下,而且,它的URI必須與parent worker的地址同源。這樣能夠很好的維持它們的依賴關係。
Timeouts 和 intervals
Workers可使用timeouts和intervals。這頗有用,例如,若是你想讓你的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 文件 javascript
JScript codehtml
var results = [];前端
var resultReceiver = function(event){html5
results.push(parseInt(event.data,10));java
if(results.length==2){web
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>
在頁面中建立了一個ID爲result的DIV用來顯示計算結果,而後建立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程序帶來更多可能性。
到底有什麼好處?來看實例更加直接一些. mozbox的Paul 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,同時計算6個Simulated annealing,能夠發現瀏覽器已經卡死,gif圖片也中止播放。
當咱們開啓workers的演示後,瀏覽器不只僅沒有卡死,同時gif圖片也正常播放,而且結果的現實比沒有開啓workers前快很多。
開發文檔地址 http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html