iT邦幫忙

DAY 28
5

HTML5試試看系列 第 28

[HTML5試試看-28] 多工 - SharedWorker

顧名思義,SharedWorker與Worker(DedicatedWorker)最大的不同,就是他可以同時為多個網頁服務。
為了驗證,我先試著使用Worker,搭配MessageChannel及window.postMessage(cross document messaging),看看是否能讓Worker與其他網頁溝通,過程如下:
(程式碼我不貼了)

  1. 網頁A用iframe內嵌網頁B
  2. 我頁A產生一個Worker及兩個MessageChannel,分別為worker, channel1與channel2
  3. 把channel1.port2與channel2.port2透過worker.postMessage()傳給worker
  4. channel1.port1網頁A留著自己用,channel2.port1則透過postMessage傳給網頁B
  5. worker透過收到的兩個MessagePort.postMessage()傳訊息給網頁A及網頁B
  6. 網頁A可以收到,但是網頁B沒有反應,而且沒有產生任何錯誤訊息

從測試看起來,Worker有限制只能與產生worker的網頁溝通。不過測試中發現了一個問題,就是Chrome7的window.postMessage()的參數與規格書規定的不一樣,Opera倒是符合規格。

接下來看看SharedWorker。他的constructor格式是new SharedWorker(scriptURL, name),只要scriptURL無誤,且scriptURL與name一致,在同一個瀏覽器,同一個origin的網頁,就可以共用SharedWorker。

SharedWorker執行期間,會透過onconnect事件接收到網頁產生SharedWorker時一併產生的MessagePort,只要在此時適當地管理這個MessagePort,就可以讓任何使用到這個SharedWorker的網頁互相溝通。來一個簡單的測試:

<html lang="zh-TW">

<meta http-equiv="Content-Type" content="text/html; charset=utf8">
<style>
	div {
		border: solid 2px #336699;
		margin: 10px;
		padding: 5px;
		border-radius: 5px;
		-moz-border-radius: 5px;
		vertical-align: top;
		text-align: center;
		display: inline-block;
	}
	#panel {
		width: 400px;
		background: #AACCEE;
		text-align: left;
		font-size: 10pt;
		display: block;
	}
</style>


<div><form id="form"><input type="text" id="msg"></form></div>
<div>Chat Messages<div id="panel"></div></div>


<script>
var shared = new SharedWorker('test646.js', 'chat');
var form = document.getElementById('form');
form.onsubmit = function(e) {
	e.preventDefault();
	var msg = document.getElementById('msg');
	shared.port.postMessage(msg.value);
	msg.value = '';
	return false;
}
shared.port.onmessage = function(e) {
	document.getElementById('panel').innerHTML += '<li>' + e.data + '</li>';
}
</script>

網頁內的程式,簡單地說,就是建立一個SharedWorker,然後把從SharedWorker收到的訊息顯示在div中。透過text input則可將輸入的文字傳給SharedWorker。

test646.js內的程式:

 var ports = []
 onconnect = function(e) {
 	if(e.ports && e.ports.length>0) {
 		for(var i=0,j=e.ports.length; i<j; i++) {
 			e.ports[i].onmessage = function(e) {
 				for(var m=0,n=ports.length; m<n; m++) {
 					ports[m].postMessage(e.data);
 				}
 			}
 			ports.push(e.ports[i]);
 		}
 	}
 };

test646.js的作用就是:

  1. 收到MessagePort時,就存進ports陣列
  2. 每次從任一MessagePort收到訊息,就對所有存放在ports中的MessagePort轉發

然後進行測試,開啟內容一樣的兩個網頁,然後輸入文字...

執行畫面:

輸入訊息:

在兩個網頁同時呈現結果:

不論使用cross-document message或是channel message機制,對於無法取得其window物件的網頁,就無法傳送訊息,這對於使用來說是一個限制。SharedWorker可以讓在同一網站內的任意網頁,共同使用它,等於就打破了這個限制。

另外,從昨天的測試中可以看到,許多瀏覽器可以讓你在Worker中使用importScripts來載入script、可以使用Worker及SharedWorker、可以使用XMLHttpRequest等等,讓Worker的功能有很大的提昇。(不過呢,這還是需要先確定瀏覽器支援「什麼」)

OK,28天來大致介紹了一些HTML5的功能及相關的API,明天來嘗試一些簡單的綜合應用好了。

參賽文章


上一篇
[HTML5試試看-27] 多工 - WebWorkers
下一篇
[HTML5試試看-29] 綜合應用
系列文
HTML5試試看30

尚未有邦友留言

立即登入留言