Html5实践之EventSource

最近尝试了一下服务器端的推送,之前的做法都是客户端轮询,定时向服务器发送请求。但这造成了我的一些困扰:

1:轮询是由客户端发起的,那么在服务端就不能判别我要推送的内容是否已经过期,因为我很难判断某个信息是否已经推送给全部的客户端,那么服务端就需要缓存大量的数据。如果数据保存在数据库,那么还要每次请求都需要查询数据库,这对数据库和系统设计都是一个很大的挑战。

2:请求的频率太高,每次的请求包中含有同样的数据,这对pc来说也许算不得什么,但是对于移动客户端来讲,这应该不是最佳的方案。尤其是遇到还要做权限判断的时候,那么服务端的逻辑和效率也会造成用户体验的降低。

好在Html5为我们提供了一种方式: Server-Sent Events包含新的HTML元素EventSource和新的MIME类型 text/event-stream 来完成我的需要。

因为是第一次接触Html5, w3school中也有对EventSource的说明和使用 。于是马上开始着手实践。

页面脚本就不用说了,按照w3school的方式即可。

var source=new EventSource("demo_sse.php");
source.onmessage=function(event)
  {
  document.getElementById("result").innerHTML+=event.data + "<br />";
  };

服务端的代码也是如初一折,w3school提供了php和asp的代码:

//php方式
<?php
header(‘Content-Type: text/event-stream‘);
header(‘Cache-Control: no-cache‘);
$time = date(‘r‘);
echo "data: The server time is: {$time}\n\n";
flush();
?>

//asp方式
<%
Response.ContentType="text/event-stream"
Response.Expires=-1
Response.Write("data: " & now())
Response.Flush()
%>
  • 把报头 "Content-Type" 设置为 "text/event-stream"
  • 规定不对页面进行缓存
  • 输出发送日期(始终以 "data: " 开头)
  • 向网页刷新输出数据

也许大家应该注意到,php和asp的案例有一点不一样,就是php推送的信息一个使用了"\n\n"作为结束标志,而asp却没有。而本人实践则是用asp.net+mvc,经过测试,如果不以"\n\n"作为结束标志,那么客户端将不能接收到推送的值。还有需要特别声明一下:推送的信息格式必须为”data:内容\n\n“,否则。。。

public void Subscribe()
        {
            HttpContext.Response.ContentType = "text/event-stream";
            HttpContext.Response.CacheControl = "no-cache";
            HttpContext.Response.Write("data:" + DateTime.Now.ToString()+ "\n\n");
            HttpContext.Response.Flush();
        }

至此,客户端应该可以收到服务端推送的值。而如此简单的结构真的可以完成我们需要的功能设计吗? 
此例我们只是推送了一个当前时间,而我们实际要推送的值是不断变化的,不然也就没有推送的必要了。

于是我想到了将订阅的请求保存起来,当需要推送的时候,在对每个请求进行循环推送,于是有了下面的代码:

public class PublishService
    {
        private static IDictionary<string, HttpResponseBase> contexts = new Dictionary<string, HttpResponseBase>();
        public static void AddHttpContext(HttpContextBase context)
        {
            var token = context.GetToken(”CookieName“);
            if (!contexts.Keys.Contains(token))
                contexts.Add(token, context.Response);
        }

        private static void Publish()
        {
            foreach (var context in contexts.Values)
            {
                context.ContentType = "text/event-stream";
                context.CacheControl = "no-cache";
                msg = GetData(context.GetToken("CookieName"));
                context.Write("data:" + msg + "\n\n");
                context.Flush();
            }
        }
        public void Subscribe()
        {
            PublishService.AddHttpContext(HttpContext);
            PublishService.Publish();
        }
    }

可是在进行测试的时候Chrome告诉我: EventSource‘s response has a MIME type ("text/plain") that is not "text/event-stream". Aborting the connection.

而FF告诉我: Firefox 无法建立到 http://localhost:8000/Location/Notification/Subscribe 服务器的连接。

经过调试发现,在每次flush的时候发生异常:Server cannot flush a completed response.这究竟是为啥呢?不论是google,还是baidu,我都没能找到合适的答案,所以此案至今未结,如哪位知道请细说一二。

于是乎,我放弃了这种方式,转而就推送一个时间看看是什么效果。结果发现Chrome每隔3秒向客户端推送一次,而FF是每5秒推送一次。有了这样一个发现,那么服务端的设计就应该是另一个样子:

public void Subscribe()
        {
            var data = GetData();

            HttpContext.Response.ContentType = "text/event-stream";
            HttpContext.Response.CacheControl = "no-cache";
            HttpContext.Response.Write("data:" + data + "\n\n");
            HttpContext.Response.Flush();
        }

服务端只需要提供一个服务GetData(),这个服务用来获取我们需要推送的信息,而根据 Server-Sent Events规范推荐如果没有其他的数据要发送,那么定期的发送keep-alive注释。 其他的事情就不用我们操心了。

这只是一个简单的使用,因为本人在使用EventSource的时候走了一些弯路,所以写出来,希望能对大家有些帮助。

求教:EventSource.onopen和EventSource.onerror每次都会触发这两个事件,而且每次得到的结果都一样,为何?

时间: 2024-07-29 15:02:26

Html5实践之EventSource的相关文章

HTML5实践 -- 使用CSS3 Media Queries实现响应式设计

转载请注明原创地址:http://www.cnblogs.com/softlover/archive/2012/11/21/2781388.html 现在屏幕分辨率的范围很大,从 320px (iPhone) 到 2560px (大型显示器),甚至更大.用户也不只是使用台式电脑访问web站点了,他使用手机.笔记本电脑.平板电脑.所以传统的设置网站宽度为固定值,已经不能满足需要了.web设计需要适应这种新要求,页面布局需要能够根据访问设备的不同分辨率自动进行调整.本教程将会向你介绍,如何使用htm

服务器推送初探

服务器推送,Comet,反向Ajax,多种名字,捯饬起来也是相当费劲. 先来看服务端: w3cSchool有个简单的例子,http://www.w3school.com.cn/html5/html_5_serversentevents.asp. 对于php,有几点需要注意: 1)设置header, header('Content-Type: text/event-stream'); 若不设置,会报错的. 2)在echo信息的时候,如果字符串过短,会不输出 最好先输出一堆空格: str_repea

平时学习HTML5及其安全相关的一些站点资源

http://www.w3.org/ -- HTML5一切标准都来自这里,如果你是发烧级HTML5患者,就读这个http://www.whatwg.org -- 和W3分分合合,最终共同指定HTML5标准http://html5.org/ -- 里面的The Web Platform做的不错,一目了然http://www.html5rocks.com -- 里面有很多知名HTML5研究者发表的文章和观点http://html5demos.com/ -- HTML5 实践DEMO最佳站点,要飞跃做

有趣的HTML5 CSS3效果

iphone6 外观:http://www.html5tricks.com/demo/css3-iphone6/index.html 天气图标:http://www.html5tricks.com/demo/pure-css3-weather-icon/index.html 3D太空船:http://www.html5tricks.com/demo/pure-css3-3d-air-ship/index.html 动态字体:http://www.html5tricks.com/demo/html

CSS3 Media Queries 实现网页自适应

文章转载自:爱思资源网http://www.aseoe.com/show-10-261-1.html 导语 接下来会展示如何运用 HTML5 和 CSS3 来设计一个自适应网页.当今银屏分辨率从 320px (iPhone) 到 2560px (大屏显示器) 或者更大.人们也不再仅仅用台式机来浏览网页,现在有手机,平板电脑等等.所以现在屏幕分辨率的范围很大,从 320px (iPhone) 到 2560px (大型显示器),甚至更大.用户也不只是使用台式电脑访问web站点了,他使用手机.笔记本电

JQueryMobile页面跳转参数的传递解决方案

在JQueryMobile开发手机端应用使用可能需要考虑相关的页面跳转带来的参数问题.因为JQueryMobile其实也是HTML5实践的结果.HTML5中有localStorage和sessionStorage使用.最好采用Storage实现比较简单易用. 例如在页面A跳转B页面,在A跳转前将跳转参数注入到localStorage中,在B页面初始化获取localStorage相关的页面参数.并做相应的处理同时在适当的页面清理页面参数. storage.js内容如下: Js代码   functi

移动端HTML5&lt;video&gt;视频播放优化实践

转帖: http://www.xuanfengge.com/html5-video-play.html 如果侵权请告知删除 遇到的挑战 移动端HTML5使用原生<video>标签播放视频,要做到两个基本原则,速度快和体验佳,先来分析一下这两个问题. 下载速度 以一个8s短视频为例,wifi环境下提供的高清视频达到1000kbps,文件大小大约1MB:非wifi环境下提供的低码率视频是500kbps左右,文件大小大约500KB:参考QzoneTouch多普勒测速,2g网络的平均速度是14KB/s

原创 HTML5:JS操作SVG实践体会

在工业信息化系统里,常常需要动态呈现系统的数据在一张示意图里,用于展现系统状态,分析结果等.这样用JavaScript操作svg 元素就有现实意义.本人近期做了一些实践,现分享一下. 需求: 你下面这样一张示意图. A1至A8,分别用显示各个检测或控制点状态,不同状态显示不同颜色.后端技术不是本文讨论重点,前端技术才是本文讨论重点.前端用H5来实现. 方案: 一.先将该示意图导出成svg格式的文件.例如”用Viso 绘图,然后导出成svg文件“. 二.在浏览器中打开svg文件,查看源码,拷贝sv

深入 HTML5 Web Worker 应用实践:多线程编程

深入 HTML5 Web Worker 应用实践:多线程编程 HTML5 中工作线程(Web Worker)简介 至 2008 年 W3C 制定出第一个 HTML5 草案开始,HTML5 承载了越来越多崭新的特性和功能.它不但强化了 Web 系统或网页的表现性能,而且还增加了对本地数据库等 Web 应用功能的支持.其中,最重要的一个便是对多线程的支持.在 HTML5 中提出了工作线程(Web Worker)的概念,并且规范出 Web Worker 的三大主要特征:能够长时间运行(响应),理想的启