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每次都会触发这两个事件,而且每次得到的结果都一样,为何?
Html5实践之EventSource的更多相关文章
- HTML5实践 -- 使用CSS3 Media Queries实现响应式设计
CSS3 Media用法介绍:http://www.w3cplus.com/content/css3-media-queries 转载请注明原创地址:http://www.cnblogs.com/so ...
- HTML5的服务器EventSource(server-sent event)发送事件
参考资料: HTML5的服务器(server-sent event)发送事件有什么应用场景? W3school HTML 5 服务器发送事件 『后台消息推送功能』,前端除了轮询.scoket.第三方服 ...
- HTML5中使用EventSource实现服务器发送事件
在HTML5的服务器发送事件中,使用EventSource对象可以接收服务器发送事件的通知. 示例: es.html <!DOCTYPE html> <html> <he ...
- HTML5实践之歌词同步播放器
歌曲播放我们会发现他的兼容性不是很好,譬如IE上能播放的flash播放器,再firfox或者chrome上就不是很好的应用了,因为有插件的阻碍!HTML5的出现让这一切成为了可能,但是播放器虽然播放了 ...
- 平时学习HTML5及其安全相关的一些站点资源
http://www.w3.org/ -- HTML5一切标准都来自这里,如果你是发烧级HTML5患者,就读这个http://www.whatwg.org -- 和W3分分合合,最终共同指定HTML5 ...
- 有趣的HTML5 CSS3效果
iphone6 外观:http://www.html5tricks.com/demo/css3-iphone6/index.html 天气图标:http://www.html5tricks.com/d ...
- JQueryMobile页面跳转参数的传递解决方案
在JQueryMobile开发手机端应用使用可能需要考虑相关的页面跳转带来的参数问题.因为JQueryMobile其实也是HTML5实践的结果.HTML5中有localStorage和sessionS ...
- spring cloud图形化dashboard是如何实现指标的收集展示的
spring cloud图形化dashboard是如何实现指标的收集展示的 1.dashboard图形化界面入口 http://localhost:10000/hystrix.stream 说明:端口 ...
- 移动端HTML5<video>视频播放优化实践
遇到的挑战 移动端HTML5使用原生<video>标签播放视频,要做到两个基本原则,速度快和体验佳,先来分析一下这两个问题. 下载速度 以一个8s短视频为例,wifi环境下提供的高清视频达 ...
随机推荐
- IOS CALayer(一)
对于一个app的好坏,我们首要判断的便是app的界面,而界面的建立则是在图形的处理基础上的,说到图形处理又不得不提及Quartz2D,CALayer. 在iOS系统中,你能看得见摸得着的东西基本上都是 ...
- IOS SizeClasses 详解
SizeClasses 详解 iOS 8在应用界面的可视化设计上添加了一个新的特性-Size Classes.对于任何设备来说,界面的宽度和高度都只分为三种描述:紧凑,任意和宽松.这样开发者便可以无视 ...
- Visual Studio发布Web项目报错:Unable to add 'xxx' to the Web site. Unable to add file 'xxx'. The specified file could not be encrypted.
背景 Visual Studio下的Web项目 现象 发布时遇到Unable to add 'xxx' to the Web site. Unable to add file 'xxx'. The ...
- Effective Java 52 Refer to objects by their interfaces
Principle If appropriate interface types exist, then parameters, return values, variables, and field ...
- Effective Java 66 Synchronize access to shared mutable data
synchronized - Only a single thread can execute a method or block at one time. Not only does synchro ...
- MVC如何在单独的类库中添加区域
今天要做一个将区域放到单独的类库中的程序,其实就是多加几个引用的问题,但是我比较喜欢这种设计结构,因为这样的话可以把单独的应用逻辑放在单独的类库中处理,项目看起来更清晰分明,所以写了这个随笔. 首先创 ...
- 关于移动端的font和图片的问题
一.font-family 使用无衬线字体 body { font-family: "Helvetica Neue", Helvetica, STHeiTi, sans-serif ...
- HTML5 自定义属性 data-* 和 jQuery.data 详解
新的HTML5标准允许你在普通的元素标签里,嵌入类似data-*的属性,来实现一些简单数据的存取.它的数量不受限制,并且也能由javascript动态修改,也支持CSS选择器进行样式设置.这使得dat ...
- Web Service中的几个重要术语
WSDL:web service definition language 直译:WebService定义语言 1.对应一种该类型的文件.WSDL 2.定义了Web Service的服务器与客户端应用交 ...
- 烂泥:LVM学习之逻辑卷、卷组及物理卷删除
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 上篇文章,我们介绍了有关LVM的逻辑卷及卷组的空间缩小.这次我们来介绍下如何删除一个逻辑卷及卷组. 删除逻辑卷需要以下几个步骤: 1. 卸载已经挂载的逻 ...