前言
本篇将讲述HTML5的服务器发送事件(server-sent event)
Server-Sent 事件
Server-Sent 事件是单向消息传递,指的是网页自动获取来自服务器的更新。
以前的做法是网页不断的询问(向服务器发送请求)是否有可用的更新。通过服务器反馈之后,获得更新。
轮训方案
我们使用上篇HTML5简单入门系列(四)web worker的技术简单实现一下该轮训方案,主动向服务器询问是否有更新。
由于web worker不能访问document等对象,是不能和jQuery连用的,这里我们实现一个简单的js原生ajax来实现向服务器发送请求。
1、新建一个WebForm页面,作为ajax请求的后端,代码很简单,只是返回当前时间即可,如下
1 protected void Page_Load(object sender, EventArgs e) 2 { 3 try 4 { 5 Response.Write("data:" + DateTime.Now); 6 Response.Flush(); 7 } 8 catch(Exception ee) 9 { 10 } 11 }
ps:这里我将webform的前台页面内容清空了,否则会同时返回页面内容。
2、按照web worker的使用方法,我们新建外部js和主线程html页面(和上篇示例中基本一致),代码如下:
webworker2.js
onmessage = function (event) { ajaxFunction("WebForm2.aspx"); } function ajaxFunction(url) { var xmlHttp; var resText; try { // Firefox, Opera 8.0+, Safari xmlHttp = new XMLHttpRequest(); // 实例化对象 } catch (e) { // Internet Explorer try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("您的浏览器不支持AJAX!"); return false; } } } xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { postMessage(xmlHttp.responseText); } } xmlHttp.open("GET", url, true); xmlHttp.send(null); }
当web worker接收到主线程启动的消息后,向webform发起请求。在XMLHTTPRequest的readystatechange事件中,服务器成功(200)返回后则postMessage回主线程更新页面。
webworker2.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> web worker实时时间:<div id="workerTime"></div> <br /> 主线程获取当前时间:<div id="curTime"></div> <button onclick="mainthread()">主线程获取时间</button> <script> var interval; if (typeof Worker != undefined) { var worker = new Worker("webworker2.js"); worker.onmessage = function (event) { document.getElementById("workerTime").textContent = event.data; } interval = setInterval('worker.postMessage()', 1000); } function mainthread() { document.getElementById("curTime").textContent = new Date(); } function stop() { clearInterval(interval); worker.terminate(); } setTimeout(stop, 60000);//60秒之后清理interval </script> </body> </html>
这里轮训时间,就是interval = setInterval('worker.postMessage()', 1000); 根据需要适当调整。
这是之前常用的轮训服务方案,而且我们接住web worker实现了多线程轮训。
HTML5 EventSource
再看看HTML5提供给我们的方案。
1、新建一个webform页面,用来充当服务器的数据更新。代码如下:
protected void Page_Load(object sender, EventArgs e) { try { Response.ContentType = "text/event-stream"; Response.CacheControl = "no-cache"; Response.Write("data:" + DateTime.Now); Response.Flush(); } catch(Exception ee) { } }
注意:这里webform的前台内容依然存在,而上边轮训服务中我将其清空了。
2、新建一个html页面,我们在该页面上实现主动数据更新。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <div id="result"></div> <script> if (typeof EventSource != undefined) { var source = new EventSource("WebForm1.aspx"); source.onmessage = function (event) { document.getElementById("result").innerHTML += event.type + ":" + event.data + "<br />"; } source.onerror = function (event) { document.getElementById("result").innerHTML += event.type + "<br />"; } } else { document.getElementById("result").innerHTML = "no support EventSource"; } </script> </body> </html>
在上面的例子中,我们使用 onmessage 事件来获取消息,onerror获取错误消息。不过还可以使用其他事件:
事件 | 描述 |
---|---|
onopen | 当通往服务器的连接被打开 |
onmessage | 当接收到消息 |
onerror | 当错误发生 |
是不是简洁多了?
另外需要说明的是,EventSource并不是实时的获取服务器更新。在Chrome浏览器中是每3秒更新一次,在Firefox浏览器中是每隔5秒更新一次
不过LZ有点不明白,为什么执行了onmessage之后还是会执行onerror呢?而且error事件中也没有太多相关信息可查看...麻烦知道的园友大牛指教!
小结
好吧,也没啥好说的,就这样吧。