HTML5 postMessage 和 onmessage API 具体应用
HTML5 postMessage 和 onmessage API 具体应用
随着 HTML5 的发展。了解并熟悉 HTML5 的 API 接口是很重要的。postMessage(send) 和 onmessage 此组 API 在 HTML5 中有着广泛的应用,比方 Web Workers 中应用此组 API 实现多个线程间 JavaScript 调用功能 ,Cross-document messaging 中实现两个不同域间 JavaScript 调用功能等等。本文主要介绍此组 API 在 Web Workers,Cross-document messaging。WebSockets
 以及 Server-Sent Events 中的具体应用情况。
0 评论:
 评论:
Web Workers
Web Workers 简单介绍
至 2008 年 W3C 制定出第一个 HTML5 草案開始。HTML5 承载了越来越多崭新的特性和功能。它不但强化了 Web 系统或网页的表现性能,并且还添加了对本地数据库等 Web 应用功能的支持。
当中,最重要的一个便是对多线程的支持。在 HTML5 中提出了工作线程(Web Workers)的概念。并且规范出 Web Workers 的三大主要特征:可以长时间执行(响应),理想的启动性能以及理想的内存消耗。Web Workers 同意开发者编写可以长时间执行而不被用户所中断的后台程序,去执行事务或者逻辑,并同一时候保证页面对用户的及时响应。
Web Workers 为 Web 前端网页上的脚本提供了一种能在后台进程中执行的方法。一旦它被创建,Web Workers 就行通过 postMessage 向任务池发送任务请求。执行完之后再通过 postMessage 返回消息给创建者指定的事件处理程序 ( 通过 onmessage 进行捕获 )。
Web Workers 进程可以在不影响用户界面的情况下处理任务。而且,它还可以使用 XMLHttpRequest 来处理 I/O,但通常,后台进程(包含 Web Workers 进程)不能对 DOM 进行操作。假设希望后台程序处理的结果可以改变
 DOM,仅仅能通过返回消息给创建者的回调函数进行处理。
浏览器对 HTML5 支持情况能够參考站点 When can I use...
在 Web Workers 中使用 postMessage 和 onmessage
首先,须要在client页面的 JavaScript 代码中 new 一个 Worker 实例出来,參数是须要在还有一个线程中执行的 JavaScript 文件名。然后在这个实例上监听 onmessage 事件。
最后还有一个线程中的 JavaScript 就能够通过调用 postMessage 方法在这两个线程间传递数据了。
清单 1. 主线程中创建 Worker 实例,并监听 onmessage 事件
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <title>Test Web worker</title>
 <script type="text/JavaScript">
	 function init(){
		 var worker = new Worker('compute.js');
		 //event 參数中有 data 属性,就是子线程中返回的结果数据
		 worker.onmessage= function (event) {
			 // 把子线程返回的结果加入到 div 上
			 document.getElementById("result").innerHTML +=
			    event.data+"<br/>";
		 };
	 }
 </script>
 </head>
 <body onload="init()">
 <div id="result"></div>
 </body>
 </html>
在client的 compute.js 中,仅仅是简单的反复多次加和操作,最后通过 postMessage 方法把结果返回给主线程,目的就是等待一段时间。而在这段时间内,主线程不应该被堵塞,用户能够通过拖拽浏览器,变大缩小浏览器窗体等操作測试这一现象。这个非堵塞主线程的结果就是 Web Workers 想达到的目的。
清单 2. compute.js 中调用 postMessage 方法返回计算结果
 var i=0; 
 function timedCount(){
	 for(var j=0,sum=0;j<100;j++){
		 for(var i=0;i<100000000;i++){
			 sum+=i;
		 }
	 }
	 // 调用 postMessage 向主线程发送消息
	 postMessage(sum);
 } 
 postMessage("Before computing,"+new Date());
 timedCount();
 postMessage("After computing,"+new Date());
图 1. 浏览器中执行结果

Cross-document messaging
Cross-document messaging 简单介绍
因为同源策略的限制。JavaScript 跨域的问题。一直是一个颇为棘手的问题。
HTML5 提供了在网页文档之间互相接收与发送信息的功能。使用这个功能,仅仅要获取到网页所在窗体对象的实例。不仅同源(域 + port号)的 Web 网页之间能够互相通信,甚至能够实现跨域通信。 要想接收从其他窗体发送来的信息,必须对窗体对象的 onmessage 事件进行监听,其他窗体能够通过 postMessage 方法来传递数据。该方法使用两个參数:第一个參数为所发送的消息文本,但也能够是不论什么 JavaScript 对象(通过 JSON
 转换对象为文本),第二个參数为接收消息的对象窗体的 URL 地址,能够在 URL 地址字符串中使用通配符'*'指定所有地。
在 Cross-document messaging 中使用 postMessage 和 onmessage
为了实现不同域之间的通信,须要在操作系统的 hosts 文件加入两个域名。进行模拟。
清单 3. hosts 文件里加入两个不同的域名
 127.0.0.1 	 parent.com
 127.0.0.1 	 child.com
在父网页中通过 iframe 嵌入子页面。并在 JavaScript 代码中调用 postMessage 方法发送数据到子窗体。
清单 4. 父页面中嵌入子页面,调用 postMessage 方法发送数据
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Test Cross-domain communication using HTML5</title>
 <script type="text/JavaScript">
	 function sendIt(){
		 // 通过 postMessage 向子窗体发送数据
		 document.getElementById("otherPage").contentWindow
			 .postMessage(
				 document.getElementById("message").value,
				"http://child.com:8080"
			 );
	 }
 </script>
 </head>
 <body>
	 <!-- 通过 iframe 嵌入子页面 -->
	 <iframe src="http://child.com:8080/TestHTML5/other-domain.html"
				 id="otherPage"></iframe>
	 <br/><br/>
	 <input type="text" id="message"><input type="button"
			 value="Send to child.com" onclick="sendIt()" />
 </body>
 </html>
在子窗体中监听 onmessage 事件,并用 JavaScript 实现显示父窗体发送过来的数据。
清单 5. 子窗体中监听 onmessage 事件,显示父窗体发送来的数据
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Web page from child.com</title>
 <script type="text/JavaScript">
	 //event 參数中有 data 属性。就是父窗体发送过来的数据
	 window.addEventListener("message", function( event ) {
		 // 把父窗体发送过来的数据显示在子窗体中
	   document.getElementById("content").innerHTML+=event.data+"<br/>";
	 }, false ); 
 </script>
 </head>
 <body>
	 Web page from http://child.com:8080
	 <div id="content"></div>
 </body>
 </html>
图 2. 父窗体嵌入子窗体

图 3. 父窗体发送数据到子窗体

WebSockets
WebSockets 简单介绍
在 Web 应用中,HTTP 协议决定了client和服务端连接是短连接,即client Request,服务端 Response。连接断开。要想实现client和服务端实时通信,仅仅能通过client轮询来实现。服务端推送数据也并非字面上意思上的直接推。事实上还是client自己取。WebSockets 是 HTML5 规范新引入的功能。用于解决浏览器与后台server双向通讯的问题,使用 WebSockets 技术,后台能够随时向前端推送消息,以保证前后台状态统一。
在 WebSockets 中使用 send 和 onmessage
因为文本主要介绍 postMessage(send) 和 onmessage client API 的应用,而 WebSockets 涉及到server端代码的实现,所以本文将选取最简单的server端框架来编写server代码。WebSockets server端有 jetty 提供的基于 Java 的实现。有 WebSocket-Node 基于 node.js 的实现,在 .Net 4.5 中也直接提供了 WebSockets 的支持。本文将使用 WebSocket-Node 提供的演示样例代码,稍作改动作为 WebSockets 的server端。
关于
 node.js 的介绍以及使用请參考 node.js 官方站点 node.js,关于 WebSocket-Node 的使用请參考 WebSocket-Node。
首先。须要在client通过 JavaScript 代码 new 一个 WebSocket 实例出来,參数是实现 WebSocket server端 URL 地址。然后在这个实例上监听 onmessage 事件接收server端发送过来的数据。当然。client也能够调用 send 方法,发送数据到server端。
清单 6. 创建 WebSocket 对象。并监听 onmessage 事件
 connect : function() {
    var location ="ws://localhost:8000/";
	 // 创建 WebSockets 并传入 WebSockets server 地址
    this._ws =new WebSocket(location);
    this._ws.onmessage=this._onmessage;
   //WebSockets 还提供了 onopen 以及 onclose 事件
    this._ws.onopen =this._onopen;
    this._ws.onclose =this._onclose;
 }
在 _onmessage 方法中,接收数据,并显示在页面上
清单 7. _onmessage 方法
 _onmessage : function(event) {
	 //event 參数中有 data 属性。就是server发送过来的数据
     if (event.data) {
         var messageBox = document.getElementById('messageBox');
         var spanText = document.createElement('span');
         spanText.className ='text';
		 // 把server发送过来的数据显示在窗体中
         spanText.innerHTML = event.data;
         var lineBreak = document.createElement('br');
         messageBox.appendChild(spanText);
         messageBox.appendChild(lineBreak);
         messageBox.scrollTop = messageBox.scrollHeight
                 - messageBox.clientHeight;
     }
 },
在 _onopen 方法中,调用 _send 方法发送一条消息到server端,告之连接已经建立。在 _onclose 方法中,把 WebSocket 的实例设置成 null,释放资源。
清单 8. _onopen,_onclose 以及 send 方法
 _onopen : function() {
     server._send("Client:Open WebSockets,"+new Date());
 },
 //message 參数就是client向服务器端发送的数据
 _send : function(message) {
     if (this._ws)
         this._ws.send(message);
 },
 // 此方法提供外部代码调用
 send : function(text) {
     if (text !=null&& text.length >0)
         server._send(text);
 }, 
 _onclose : function(m) {
     this._ws =null;
 }
把这些方法封装在一个 server 对象中。方便提供外部调用。用户仅仅须要先调用 server 的 connect 方法建立连接,然后调用 send 方法发送数据。
清单 9. 封装client实现
 var server = {
	 // 对外主要提供 connect 和 send 方法
    connect : function() {...},
    _onopen : function() {...},
    _send : function(message) {...},
    send : function(text) {...},
    _onmessage : function(event) {...},
    _onclose : function(m) {...}
 };
在服务器端,通过 JavaScript 语言简单改动 WebSocket-Node 中提供的 echo-server.js 演示样例就可以。
这里仅仅展示关键代码部分,其他代码请參见 WebSocket-Node 演示样例。
清单 10. WebSockets server端简单实现
 // 监听client的连接请求
 wsServer.on('connect', function(connection) {
    function sendCallback(err) {
        if (err) console.error("send() error: " + err);
    }
	 // 监听client发送数据的请求
    connection.on('message', function(message) {
        if (message.type === 'utf8') {// 差别client发过来的数据是文本还是二进制类型
            connection.sendUTF(
				"Server:Get message:<br/>"+message.utf8Data, sendCallback
			 );
        }
        else if (message.type === 'binary') {
            connection.sendBytes(message.binaryData, sendCallback);
        }
    });
    connection.on('close', function(reasonCode, description) {
    });
 });
图 4. 点击 Connect button

图 5. 输入内容,单击 Send Message button

Server-Sent Events
Server-Sent Events 简单介绍
HTML5 Server-Sent 事件模型同意您从server push 实时数据到浏览器。本文我们将介绍利用 Eventsource 对象处理与页面间的接收和发送数据。在client。我们使用 HTML5+JavaScript。服务端使用 Java。在现存的 Ajax 模式中,web 页面会持续不断地请求server传输新数据,由client负责请求数据。而在服务端发送模式下。无需在client代码中运行连续的数据请求。而是由服务端 push 推送更新。一旦您在页面中初始化了 Server-Sent 事件。服务端脚本将持续地发送更新。
client
 JavaScript 代码一旦接收到更新就将新的数据写入页面中展示出来。
在 Server-Sent Events 中使用 onmessage
Server-Sent Events 和 WebSockets 有相同之处,WebSockets 实现了server端以及client的双向通信功能,而 Server-Sent Events 则仅是指server端到client的单向通信。并且 Server-Sent Events 相同须要server端的实现。本文将使用基于 Java 的 Servlet 技术实现server端。
关于server端向client写数据的格式。能够參考 W3C 关于 Server-Sent Events 的规范文档 Server-Sent
 Events。因为是server端到client的单向通信。所以在 Server-Sent Events 中没有 postMessage 方法。
首先,在client通过 JavaScript 代码 new 一个 EventSource 实例出来,參数是实现 EventSource server端 URL 地址。
然后在这个实例上监听 onmessage 事件接收server端发送过来的数据。
清单 11. 创建 EventSource 对象,并监听 onmessage 事件
 if (!!window.EventSource) {
 // 创建 EventSource 实例,传入 server 地址
	  var source = new EventSource('/TestHTML5/ServerSentEvent');
	 } else {
	  console.log("Your browser doesn't support server-sent event");
 }
 // 监听 message 事件,等待接收服务器端发送过来的数据
 source.addEventListener('message', function(event) {
		 //event 參数中有 data 属性,就是服务器发送过来的数据
	  console.log(event.data);
 }, false); 
 //EventSource 还提供了 onopen 以及 onerror 事件
 source.addEventListener('open', function(event) {
 }, false); 
 source.addEventListener('error', function(event) {
	 if (event.readyState == EventSource.CLOSED) {
	  }
 }, false);
server端,在 Java 语言实现的 Servlet doGet 方法中使用 response 对象向client写数据
清单 10. server端简单实现
 // 这里必须设置 Content-Type 为 text/event-stream
 response.setHeader("Content-Type", "text/event-stream");
 response.setHeader("Cache-Control", "no-cache");
 response.setCharacterEncoding ("UTF-8"); 
 String id = new Date().toString();
 response.getWriter().println("id:"+id);
 // 向client写两行数据
 response.getWriter().println("data:server-sent event is working.");
 response.getWriter().println("data:test server-sent event multi-line data");
 response.getWriter().println();
 response.getWriter().flush();
图 6. Server-Sent Events 执行结果

结束语
本文具体介绍了 postMessage(send)和 onmessage API 在client的应用情况。能够看到在不同的场景中这两个方法的应用模式都是类似的。
postMessage 的作用就是传递数据,而 onmessage 的作用就是接收数据。
掌握此组 API 对以后开发 HTML 5 应用程序将会有所帮助。本文 Web Workers,Cross-document messaging,WebSockets 的代码在 Firefox 14 下通过測试,Server-Sent Events 的代码在 Chrome
 16 下通过測试。
下载
參考资料
学习
- 关于 HTML5 的规范,请參考 HTML5
- 关于 HTML5 WebSockets 的规范。请參考 WebSockets。
- 关于 HTML5 Web Workers 的规范,请參考 Web Workers。
- 关于 HTML5 Cross-document messaging 的规范,请參考 Cross-document messaging。
- 关于 HTML5 Server-Sent Events 的规范,请參考 Server-Sent Events。
- 关于 node.js 的信息,请參考 node.js。
- 关于 WebSocket-Node 的信息。请參考 WebSocket-Node。
- developerWorks Web development 专区:通过专门关于 Web
 技术的文章和教程。扩展您在站点开发方面的技能。
- developerWorks Ajax 资源中心:这是有关 Ajax 编程模型信息的一站式中心。包含非常多文档、教程、论坛、blog、wiki
 和新闻。不论什么 Ajax 的新信息都能在这里找到。
- developerWorks Web 2.0 资源中心,这是有关 Web 2.0
 相关信息的一站式中心,包含大量 Web 2.0 技术文章、教程、下载和相关技术资源。
- 查看 HTML5 专题,了解很多其它和 HTML5 相关的知识和动向。
讨论
- 增加 developerWorks 中文社区。查看开发者推动的博客、论坛、组和维基,并与其它
 developerWorks 用户交流。
HTML5 postMessage 和 onmessage API 具体应用
随着 HTML5 的发展。了解并熟悉 HTML5 的 API 接口是很重要的。postMessage(send) 和 onmessage 此组 API 在 HTML5 中有着广泛的应用,比方 Web Workers 中应用此组 API 实现多个线程间 JavaScript 调用功能 ,Cross-document messaging 中实现两个不同域间 JavaScript 调用功能等等。本文主要介绍此组 API 在 Web Workers,Cross-document messaging。WebSockets
 以及 Server-Sent Events 中的具体应用情况。
0 评论:
 评论:
Web Workers
Web Workers 简单介绍
至 2008 年 W3C 制定出第一个 HTML5 草案開始。HTML5 承载了越来越多崭新的特性和功能。它不但强化了 Web 系统或网页的表现性能,并且还添加了对本地数据库等 Web 应用功能的支持。
当中,最重要的一个便是对多线程的支持。在 HTML5 中提出了工作线程(Web Workers)的概念。并且规范出 Web Workers 的三大主要特征:可以长时间执行(响应),理想的启动性能以及理想的内存消耗。Web Workers 同意开发者编写可以长时间执行而不被用户所中断的后台程序,去执行事务或者逻辑,并同一时候保证页面对用户的及时响应。
Web Workers 为 Web 前端网页上的脚本提供了一种能在后台进程中执行的方法。一旦它被创建,Web Workers 就行通过 postMessage 向任务池发送任务请求。执行完之后再通过 postMessage 返回消息给创建者指定的事件处理程序 ( 通过 onmessage 进行捕获 )。
Web Workers 进程可以在不影响用户界面的情况下处理任务。而且,它还可以使用 XMLHttpRequest 来处理 I/O,但通常,后台进程(包含 Web Workers 进程)不能对 DOM 进行操作。假设希望后台程序处理的结果可以改变
 DOM,仅仅能通过返回消息给创建者的回调函数进行处理。
浏览器对 HTML5 支持情况能够參考站点 When can I use...
在 Web Workers 中使用 postMessage 和 onmessage
首先,须要在client页面的 JavaScript 代码中 new 一个 Worker 实例出来,參数是须要在还有一个线程中执行的 JavaScript 文件名。然后在这个实例上监听 onmessage 事件。
最后还有一个线程中的 JavaScript 就能够通过调用 postMessage 方法在这两个线程间传递数据了。
清单 1. 主线程中创建 Worker 实例,并监听 onmessage 事件
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Test Web worker</title>
<script type="text/JavaScript">
function init(){
var worker = new Worker('compute.js');
//event 參数中有 data 属性,就是子线程中返回的结果数据
worker.onmessage= function (event) {
// 把子线程返回的结果加入到 div 上
document.getElementById("result").innerHTML +=
event.data+"<br/>";
};
}
</script>
</head>
<body onload="init()">
<div id="result"></div>
</body>
</html>
在client的 compute.js 中,仅仅是简单的反复多次加和操作,最后通过 postMessage 方法把结果返回给主线程,目的就是等待一段时间。而在这段时间内,主线程不应该被堵塞,用户能够通过拖拽浏览器,变大缩小浏览器窗体等操作測试这一现象。这个非堵塞主线程的结果就是 Web Workers 想达到的目的。
清单 2. compute.js 中调用 postMessage 方法返回计算结果
 var i=0; 
 function timedCount(){
	 for(var j=0,sum=0;j<100;j++){
		 for(var i=0;i<100000000;i++){
			 sum+=i;
		 }
	 }
	 // 调用 postMessage 向主线程发送消息
	 postMessage(sum);
 } 
 postMessage("Before computing,"+new Date());
 timedCount();
 postMessage("After computing,"+new Date());
图 1. 浏览器中执行结果

Cross-document messaging
Cross-document messaging 简单介绍
因为同源策略的限制。JavaScript 跨域的问题。一直是一个颇为棘手的问题。
HTML5 提供了在网页文档之间互相接收与发送信息的功能。使用这个功能,仅仅要获取到网页所在窗体对象的实例。不仅同源(域 + port号)的 Web 网页之间能够互相通信,甚至能够实现跨域通信。 要想接收从其他窗体发送来的信息,必须对窗体对象的 onmessage 事件进行监听,其他窗体能够通过 postMessage 方法来传递数据。该方法使用两个參数:第一个參数为所发送的消息文本,但也能够是不论什么 JavaScript 对象(通过 JSON
 转换对象为文本),第二个參数为接收消息的对象窗体的 URL 地址,能够在 URL 地址字符串中使用通配符'*'指定所有地。
在 Cross-document messaging 中使用 postMessage 和 onmessage
为了实现不同域之间的通信,须要在操作系统的 hosts 文件加入两个域名。进行模拟。
清单 3. hosts 文件里加入两个不同的域名
127.0.0.1 parent.com
127.0.0.1 child.com
在父网页中通过 iframe 嵌入子页面。并在 JavaScript 代码中调用 postMessage 方法发送数据到子窗体。
清单 4. 父页面中嵌入子页面,调用 postMessage 方法发送数据
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Cross-domain communication using HTML5</title>
<script type="text/JavaScript">
function sendIt(){
// 通过 postMessage 向子窗体发送数据
document.getElementById("otherPage").contentWindow
.postMessage(
document.getElementById("message").value,
"http://child.com:8080"
);
}
</script>
</head>
<body>
<!-- 通过 iframe 嵌入子页面 -->
<iframe src="http://child.com:8080/TestHTML5/other-domain.html"
id="otherPage"></iframe>
<br/><br/>
<input type="text" id="message"><input type="button"
value="Send to child.com" onclick="sendIt()" />
</body>
</html>
在子窗体中监听 onmessage 事件,并用 JavaScript 实现显示父窗体发送过来的数据。
清单 5. 子窗体中监听 onmessage 事件,显示父窗体发送来的数据
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Web page from child.com</title>
<script type="text/JavaScript">
//event 參数中有 data 属性。就是父窗体发送过来的数据
window.addEventListener("message", function( event ) {
// 把父窗体发送过来的数据显示在子窗体中
document.getElementById("content").innerHTML+=event.data+"<br/>";
}, false ); </script>
</head>
<body>
Web page from http://child.com:8080
<div id="content"></div>
</body>
</html>
图 2. 父窗体嵌入子窗体

图 3. 父窗体发送数据到子窗体

WebSockets
WebSockets 简单介绍
在 Web 应用中,HTTP 协议决定了client和服务端连接是短连接,即client Request,服务端 Response。连接断开。要想实现client和服务端实时通信,仅仅能通过client轮询来实现。服务端推送数据也并非字面上意思上的直接推。事实上还是client自己取。WebSockets 是 HTML5 规范新引入的功能。用于解决浏览器与后台server双向通讯的问题,使用 WebSockets 技术,后台能够随时向前端推送消息,以保证前后台状态统一。
在 WebSockets 中使用 send 和 onmessage
因为文本主要介绍 postMessage(send) 和 onmessage client API 的应用,而 WebSockets 涉及到server端代码的实现,所以本文将选取最简单的server端框架来编写server代码。WebSockets server端有 jetty 提供的基于 Java 的实现。有 WebSocket-Node 基于 node.js 的实现,在 .Net 4.5 中也直接提供了 WebSockets 的支持。本文将使用 WebSocket-Node 提供的演示样例代码,稍作改动作为 WebSockets 的server端。
关于
 node.js 的介绍以及使用请參考 node.js 官方站点 node.js,关于 WebSocket-Node 的使用请參考 WebSocket-Node。
首先。须要在client通过 JavaScript 代码 new 一个 WebSocket 实例出来,參数是实现 WebSocket server端 URL 地址。然后在这个实例上监听 onmessage 事件接收server端发送过来的数据。当然。client也能够调用 send 方法,发送数据到server端。
清单 6. 创建 WebSocket 对象。并监听 onmessage 事件
 connect : function() {
    var location ="ws://localhost:8000/";
	 // 创建 WebSockets 并传入 WebSockets server 地址
    this._ws =new WebSocket(location);
    this._ws.onmessage=this._onmessage;
   //WebSockets 还提供了 onopen 以及 onclose 事件
    this._ws.onopen =this._onopen;
    this._ws.onclose =this._onclose;
 }
在 _onmessage 方法中,接收数据,并显示在页面上
清单 7. _onmessage 方法
 _onmessage : function(event) {
	 //event 參数中有 data 属性。就是server发送过来的数据
     if (event.data) {
         var messageBox = document.getElementById('messageBox');
         var spanText = document.createElement('span');
         spanText.className ='text';
		 // 把server发送过来的数据显示在窗体中
         spanText.innerHTML = event.data;
         var lineBreak = document.createElement('br');
         messageBox.appendChild(spanText);
         messageBox.appendChild(lineBreak);
         messageBox.scrollTop = messageBox.scrollHeight
                 - messageBox.clientHeight;
     }
 },
在 _onopen 方法中,调用 _send 方法发送一条消息到server端,告之连接已经建立。在 _onclose 方法中,把 WebSocket 的实例设置成 null,释放资源。
清单 8. _onopen,_onclose 以及 send 方法
 _onopen : function() {
     server._send("Client:Open WebSockets,"+new Date());
 },
 //message 參数就是client向服务器端发送的数据
 _send : function(message) {
     if (this._ws)
         this._ws.send(message);
 },
 // 此方法提供外部代码调用
 send : function(text) {
     if (text !=null&& text.length >0)
         server._send(text);
 }, 
 _onclose : function(m) {
     this._ws =null;
 }
把这些方法封装在一个 server 对象中。方便提供外部调用。用户仅仅须要先调用 server 的 connect 方法建立连接,然后调用 send 方法发送数据。
清单 9. 封装client实现
 var server = {
	 // 对外主要提供 connect 和 send 方法
    connect : function() {...},
    _onopen : function() {...},
    _send : function(message) {...},
    send : function(text) {...},
    _onmessage : function(event) {...},
    _onclose : function(m) {...}
 };
在服务器端,通过 JavaScript 语言简单改动 WebSocket-Node 中提供的 echo-server.js 演示样例就可以。
这里仅仅展示关键代码部分,其他代码请參见 WebSocket-Node 演示样例。
清单 10. WebSockets server端简单实现
// 监听client的连接请求
wsServer.on('connect', function(connection) {
function sendCallback(err) {
if (err) console.error("send() error: " + err);
}
// 监听client发送数据的请求
connection.on('message', function(message) {
if (message.type === 'utf8') {// 差别client发过来的数据是文本还是二进制类型
connection.sendUTF(
"Server:Get message:<br/>"+message.utf8Data, sendCallback
);
}
else if (message.type === 'binary') {
connection.sendBytes(message.binaryData, sendCallback);
}
});
connection.on('close', function(reasonCode, description) {
});
});
图 4. 点击 Connect button

图 5. 输入内容,单击 Send Message button

Server-Sent Events
Server-Sent Events 简单介绍
HTML5 Server-Sent 事件模型同意您从server push 实时数据到浏览器。本文我们将介绍利用 Eventsource 对象处理与页面间的接收和发送数据。在client。我们使用 HTML5+JavaScript。服务端使用 Java。在现存的 Ajax 模式中,web 页面会持续不断地请求server传输新数据,由client负责请求数据。而在服务端发送模式下。无需在client代码中运行连续的数据请求。而是由服务端 push 推送更新。一旦您在页面中初始化了 Server-Sent 事件。服务端脚本将持续地发送更新。
client
 JavaScript 代码一旦接收到更新就将新的数据写入页面中展示出来。
在 Server-Sent Events 中使用 onmessage
Server-Sent Events 和 WebSockets 有相同之处,WebSockets 实现了server端以及client的双向通信功能,而 Server-Sent Events 则仅是指server端到client的单向通信。并且 Server-Sent Events 相同须要server端的实现。本文将使用基于 Java 的 Servlet 技术实现server端。
关于server端向client写数据的格式。能够參考 W3C 关于 Server-Sent Events 的规范文档 Server-Sent
 Events。因为是server端到client的单向通信。所以在 Server-Sent Events 中没有 postMessage 方法。
首先,在client通过 JavaScript 代码 new 一个 EventSource 实例出来,參数是实现 EventSource server端 URL 地址。
然后在这个实例上监听 onmessage 事件接收server端发送过来的数据。
清单 11. 创建 EventSource 对象,并监听 onmessage 事件
 if (!!window.EventSource) {
 // 创建 EventSource 实例,传入 server 地址
	  var source = new EventSource('/TestHTML5/ServerSentEvent');
	 } else {
	  console.log("Your browser doesn't support server-sent event");
 }
 // 监听 message 事件,等待接收服务器端发送过来的数据
 source.addEventListener('message', function(event) {
		 //event 參数中有 data 属性,就是服务器发送过来的数据
	  console.log(event.data);
 }, false); 
 //EventSource 还提供了 onopen 以及 onerror 事件
 source.addEventListener('open', function(event) {
 }, false); 
 source.addEventListener('error', function(event) {
	 if (event.readyState == EventSource.CLOSED) {
	  }
 }, false);
server端,在 Java 语言实现的 Servlet doGet 方法中使用 response 对象向client写数据
清单 10. server端简单实现
// 这里必须设置 Content-Type 为 text/event-stream
response.setHeader("Content-Type", "text/event-stream");
response.setHeader("Cache-Control", "no-cache");
response.setCharacterEncoding ("UTF-8"); String id = new Date().toString();
response.getWriter().println("id:"+id);
// 向client写两行数据
response.getWriter().println("data:server-sent event is working.");
response.getWriter().println("data:test server-sent event multi-line data");
response.getWriter().println();
response.getWriter().flush();
图 6. Server-Sent Events 执行结果

结束语
本文具体介绍了 postMessage(send)和 onmessage API 在client的应用情况。能够看到在不同的场景中这两个方法的应用模式都是类似的。
postMessage 的作用就是传递数据,而 onmessage 的作用就是接收数据。
掌握此组 API 对以后开发 HTML 5 应用程序将会有所帮助。本文 Web Workers,Cross-document messaging,WebSockets 的代码在 Firefox 14 下通过測试,Server-Sent Events 的代码在 Chrome
 16 下通过測试。
下载
參考资料
学习
- 关于 HTML5 的规范,请參考 HTML5
- 关于 HTML5 WebSockets 的规范。请參考 WebSockets。
- 关于 HTML5 Web Workers 的规范,请參考 Web Workers。
- 关于 HTML5 Cross-document messaging 的规范,请參考 Cross-document messaging。
- 关于 HTML5 Server-Sent Events 的规范,请參考 Server-Sent Events。
- 关于 node.js 的信息,请參考 node.js。
- 关于 WebSocket-Node 的信息。请參考 WebSocket-Node。
- developerWorks Web development 专区:通过专门关于 Web
 技术的文章和教程。扩展您在站点开发方面的技能。
- developerWorks Ajax 资源中心:这是有关 Ajax 编程模型信息的一站式中心。包含非常多文档、教程、论坛、blog、wiki
 和新闻。不论什么 Ajax 的新信息都能在这里找到。
- developerWorks Web 2.0 资源中心,这是有关 Web 2.0
 相关信息的一站式中心,包含大量 Web 2.0 技术文章、教程、下载和相关技术资源。
- 查看 HTML5 专题,了解很多其它和 HTML5 相关的知识和动向。
讨论
- 增加 developerWorks 中文社区。查看开发者推动的博客、论坛、组和维基,并与其它
 developerWorks 用户交流。
HTML5 postMessage 和 onmessage API 具体应用的更多相关文章
- HTML5 postMessage 和 onmessage API 详细应用
		随着 HTML5 的发展,了解并熟悉 HTML5 的 API 接口是非常重要的.postMessage(send) 和 onmessage 此组 API 在 HTML5 中有着广泛的应用,比如 Web ... 
- HTML5 postMessage 跨域交换数据
		前言 之前简单讲解了利用script标签(jsonp)以及iframe标签(window.name.location.hash)来跨域交换数据,今天我们来学习一下HTML5的api,利用postMes ... 
- 通过Html5的postMessage和onMessage方法实现跨域跨文档请求访问
		在项目中有应用到不同的子项目,通过不同的二级域名实现相互调用功能.其中一个功能是将播放器作为单独的二级域名的请求接口,其他项目必须根据该二级域名调用播放器.最近需要实现视频播放完毕后的事件触发,调用父 ... 
- [转]html5: postMessage解决跨域和跨页面通信的问题
		[转]html5: postMessage解决跨域和跨页面通信的问题 平时做web开发的时候关于消息传递,除了客户端与服务器传值,还有几个经常会遇到的问题: 多窗口之间消息传递(newWin = wi ... 
- HTML5之本地文件系统API - File System API
		HTML5之本地文件系统API - File System API 新的HTML5标准给我们带来了大量的新特性和惊喜,例如,画图的画布Canvas,多媒体的audio和video等等.除了上面我们提到 ... 
- 跨域问题实践总结!下( [HTML5] postMessage+服务器端(反向代理服务器+CORS Cross-Origin Resource Sharing))
		4. [HTML5] postMessage 问题: 对于跨域问题,研究了一下html5的postMessage,写了代码测试了一下,感觉html5新功能就是好用啊.此文仅使用html5的新特性pos ... 
- HTML5语音合成Speech Synthesis API简介
		by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=5865本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随意 ... 
- html5获取地理位置信息API
		html5获取地理位置信息API 在HTML5中,可以看下如何使用Geolocation API来获得用户的地理位置信息,如果该浏览器支持的话,且设备具有定位功能,就能够直接使用这组API来获取当前位 ... 
- 使用HTML5的两个api,前端js完成图片压缩
		主要用了两个html5的 API,一个file,一个canvas,压缩主要使用cnavas做的,file是读取文件,之后把压缩好的照片放入内存,最后内存转入表单下img.src,随着表单提交. 照片是 ... 
随机推荐
- hdu 2222 Keywords Search    ac自动机模板
			题目链接 先整理一发ac自动机模板.. #include <iostream> #include <vector> #include <cstdio> #inclu ... 
- 一些CSS命名规则
			一些CSS命名规则 头:header 内容:content/containe 尾:footer 导航:nav 侧栏:sidebar 栏目:column 页面外围控制整体布局宽度:wrapper 左右中 ... 
- android select选择器 checkbox改外观,button按下状态
			android 可以用选择器.来加载视图.选择器里的选项也很多针对实际使用中用的几个进行描述. 1.button 的按下弹起改外观.选择器属性用 android:state_pressed 2.C ... 
- Umbraco Content属性
			总算是有个内容还算多的Content的属性介绍,保存一下. https://our.umbraco.org/documentation/Reference/Management-v6/Models/C ... 
- 关于Apple Pay,一篇让你不看就会后悔的文章
			编者按:本文作者康上明学为“小米生活”产品经理,在苹果Apple Pay发布后,他对该产品做了深入研究,带来这篇文章. 对于 Apple Pay ,我有几个疑问: 线下支付是一个庞大复杂的流程,当中涉 ... 
- Win7下qt5.3.1+opencv2.4.9编译环境的搭建(好多 Opencv2.4.9源码分析的博客)
			到官网下载qt-opensource-windows-x86-mingw482_opengl-5.3.1.exe文件,执行该文件,选择默认安装即可实现QT的安装(安装在C盘的根目录下),该文件封装 ... 
- Unix/Linux环境C编程入门教程(14) Mandriva LinuxCCPP开发环境搭建
			1. Mandriva是目前全球最优秀的Linux发行版之一,稳居于linux排行榜第一梯队. Mandriva公司现在仍然是 这个时候mandriva Linux系统安装完成,基于Mandriva的 ... 
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(三)
			我们已经设计了一个基于qemu的watchdog了.下一步工作就是创建一个含有我们的watchdog的虚拟计算机器了. 准备工作: 1. 使用virt-manager或者virsh创建一个虚拟机器. ... 
- 一步一步挖出Compute
			前几天在做结账的时候,对数据表DataGridView控件的单列求和纠结了一番. 如今差点儿养成了习惯,对于一些东西疏于開始的思考,不会先想到百度,这里我是先想到了第一版的机房收费那块的 ... 
- JavaScript之Style属性学习
			当CSS使用伪类开始侵入DOM和JavaSCript所控制着的行为层时,DOM和JavaScript也使用他们的一系列样式去控制表现层,这篇随笔主要说的就是利用JavaScript去控制元素的表现形式 ... 
 
			
		 内容
内容