iT邦幫忙

DAY 19
8

HTML5試試看系列 第 19

[HTML5試試看-19] 溝通 - channel message

根據規格書的解釋,channel messaging與cross-document messaging的差別在於,他提供了一個全雙工的溝通管道,所以理論上不同的網頁可以同時寫入/讀出訊息。不過我一時想不出方法怎樣來測試這個「全雙工」...所以還是簡單測試一下吧。
Channel Messaging會使用到好幾個物件來協作,包括MessagePortArray, MessagePort以及MessageChannel。每個MessageChannel裡面有兩個MessagePort,就像管線的兩端,兩個要溝通的文件各使用一端,就可以互相溝通。

MessagePortArray是一個裡面只包含MessagePort物件的陣列。MessagePort有start()、close()以及postMessage(),每個port需要先start(),才能使用postMessage傳送訊息。接收訊息則需要使用MessagePort的onmessage事件,用非同步的方式來讓事件處理函數處理。MessageChannel在使用時必須先用new MessageChannel()產生實例,他的構成很簡單,就是兩個MessagePort,分別名為port1及port2。

在使用上通需要額外透過cross document messaging的postMessage(),把另外一個MessagePort傳遞給另外一端,這個postMessage()第三個參數必須是一個MessagePortArray,所以需要的話,可以new好幾個MessageChannel,然後用陣列同時傳幾個MessagePort給對方。

下面的範例程式其實跟昨天試用cross document message的測試程式差不多,只是訊息改成用MessagePort傳遞,而cross document message只用來傳送MessagePortArray:

...耶,長度又超過限制,我放上plurk paste好了,語法highlight比較漂亮:
http://paste.plurk.com/show/323246/

iframe中使用的test632a.html如下:

<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;
		vertical-align: top;
		text-align: center;
		display: inline-block;
	}
	#container {
		background: #88BBFF;
		width: 480px;
	}
	.panel {
		background: #99CCFF;
		border: dotted 1px #4477AA;
		width: 90%;
		margin: 0px;
		text-align: left;
		font-size: 12px;
	}
</style>


<div id="container">Received messages.<div id="panel1" class="panel"></div><div id="panel2" class="panel"></div>


<script>
try {
window.addEventListener('message', function(e) {
	var port1 = null;
	var port2 = null;
	if(e.data == 'hello' && e.ports.length > 0) {
		port1 = e.ports[0];
	}
	port1.start();
	port1.addEventListener('message', function(e) {
		var str = '<li>';
		str += '[' + e.origin + ']';
		str += '[' + e.ports + ']';
		str += ' : ';
		str += e.data;
		str += '</li>\n';
		document.getElementById('panel1').innerHTML += str;
		port1.postMessage('got it at '+(new Date())+'.');
		if(e.ports) {
			port2 = e.ports[0];
			port2.start();
			port2.addEventListener('message', function(e) {
				var str = '<li>';
				str += '[' + e.origin + ']';
				str += '[' + e.ports + ']';
				str += ' : ';
				str += e.data;
				str += '</li>\n';
				document.getElementById('panel2').innerHTML += str;
				port2.postMessage('got it at '+(new Date())+'.');
			}, false);
		}
	}, false);
}, false);
}catch(e){alert(e);};
</script>

程式中首先用postMessage()傳了一個MessagePort到test632a.html,接下來透過第一次使用MessagePort.postMessage(msg, MessagePortArray)的第二個參數再傳了一個MessagePort到test632a.html,接下來就使用兩個channel來傳送同樣訊息,但是各自顯示在兩個block上。執行結果像這樣:

測試過程中發現最大的問題是...目前只有Opera瀏覽器正確無誤地支援Channel Messaging,Chrome7雖然可以使用MessageChannel,但是用postMessage傳送port到另一個文件時會出現錯誤,所以等於沒支援。

參賽文章


上一篇
[HTML5試試看-18] 溝通 - cross document message
下一篇
[HTML5試試看-20] 溝通 - server sent event
系列文
HTML5試試看30

尚未有邦友留言

立即登入留言