iT邦幫忙

DAY 6
2

Javascript面面觀系列 第 6

Javascript面面觀:核心篇《Web worker-多執行緒模型》

上一篇分享講到Javascript的單執行緒特性,以及它如何用事件佇列的方式來模擬多工。不過HTML5規格其實已經為在網頁中執行的Javascript帶來真正多執行緒的功能,這就是Web Worker。

其實不論上一篇分享或這一篇講的東西都不是定義在ECMA-262 Edition 3或即將出來的Edition 5的東西,而是網頁相關的規格。不過對於事件機制的底層實作不論ECMA-262或是DOM標準文件都沒有制定這一部份的標準,不過HTML5裡面有了!有興趣的話可以參考http://www.w3.org/TR/html5/browsers.html#event-loops
Web Worker
Worker是HTML5規格中定義的新功能,有一些參考網站:
* w3研發中標準文件-http://dev.w3.org/html5/workers/
* mozilla網站上的介紹-https://developer.mozilla.org/En/Using\_DOM\_workers
* mozilla網站上的參考文件-https://developer.mozilla.org/En/DOM/Worker

簡單地說,Web Worker是一個完全獨立的,執行Javascript的執行緒,主頁面與Worker之間,只透過postMessage函數與onmessage事件來溝通。postMessage用來向Worker物件傳送訊息,而Worker收到訊息時,則使用onmessage的事件處理函數來處理。發生錯誤時,則產生onerror事件。onmessage事件處理函數的第一個參數,會有一個屬性叫做data,攜帶傳送的資料。onerror事件處理函數的第一個參數則有三個屬性,message裡面是錯誤訊息,filename是worker執行的Javascript檔名,lineno則是發生錯誤的行數。另外,Worker物件還有一個方法叫做terminate(),可以強制結束其執行。下面列出相關的方法及屬性:

Worker物件
* 方法

  1. postMessage()
  2. terminate()
    * 事件
  3. onmessage
  4. onerror

WorkerGlobal(就是Worker的Javascript執行時的Global物件)
* 方法

  1. postMessage()
  2. close()(目前Firefox及Chrome都沒有實作這個方法,但是在HTML5 Web Worker有定義)
  3. setTimeout()
  4. clearTimeout()
  5. setInterval()
  6. clearInterval()
    * 物件
  7. Worker (目前只有Firefox3.5實作)
  8. XMLHttpRequest
    * 事件
  9. onmessage

目前的瀏覽器,只有Firefox3.5支援比較完整,在Worker裡還可以產生新的Worker。Chrome3以及Safari4支援Worker,但是沒辦法在Worker裡面產生Worker。

在Worker的使用上,傳遞給Worker的資料或回傳的資料,可以是數字、字串、陣列或物件,但是不能是函數。以下是一個簡單的例子,只能在Firefox3.5執行:

 <script>
 (function (){
 	with (new Worker("iron018.js")) {
 		onmessage = function(event) {
 			alert(event.data.msg);
 			terminate();
 		};
 		onerror = function(event) {
 			alert("error:"+event.message+" in "+event.filename+" line:"+event.lineno);
 			terminate();
 		};
 		postMessage("go");
 	}
 })();
 </script>
 
 






 onmessage = function(event) {
 	var self = this;
 	worker = new Worker("iron018a.js");
 	worker.onmessage = function(event) {
 		self.postMessage(event.data);
 		this.terminate();
 	};
 	worker.onerror = function(event) {
 		self.postMessage("error:"+event.message+" in "+event.filename+" line:"+event.lineno);
 		this.terminate();
 	};
 	var tid = setTimeout(function(){worker.postMessage("go");clearTimeout(tid);}, 100);
 }
 onerror = function(event) {
 	postMessage("error:"+event.message+" in "+event.filename+" line:"+event.lineno);
 };

(iron018.js)

 onmessage = function(event) {
 	postMessage({
 		from: 'iron018a.js',
 		msg: 'it worked.'
 	});
 }
 onerror = function(event) {
 	postMessage("error:"+event.message+" in "+event.filename+" line:"+event.lineno);
 };

(iron018a.js)

這個例子只是讓產生的Worker再產生一個Worker然後回傳訊息。

更複雜的例子可以參見我之前寫的文章:[Firefox 3.5 preview] web worker thread以及Safari的Web Worker速度非常搶眼

Web Worker可以讓花時間的程式在背景跑而不影響前景程式的使用,預料可以讓網頁程式的功能更加強大。另外,對網頁程式來說Web Worker是一個share nothing的分散式架構,有興趣的話可以用他來練習分散式運算,應該會很有趣。


上一篇
Javascript面面觀:核心篇《Timer與事件-單執行緒模型》
下一篇
Javascript面面觀:核心篇《模式-lazy load》
系列文
Javascript面面觀30

尚未有邦友留言

立即登入留言