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环境下提供的高清视频达 ...
随机推荐
- 菜鸟教程 Python100例 之实例29
学习编程的路,走得好艰辛... 为了巩固基础知识,把菜鸟教程网上的实例拿来练习.. 在做到实例29时,看了网站给出的代码,觉得可以加强一下功能,不由得动了一下脑筋,如下: 原文题目: 题目:给一个不多 ...
- 2013MPD上海6.23 PM 光耀:读心术,用户心理的产品之道
创新的前提是:制度与组织的创新!!!!!!!!!!!!!! 光耀:腾讯互联网业务产品经理(腾讯公司互联网业务系统产品经理.在电子商务.社会化媒体等方面有深入研究.参与腾讯多个重要项目产品工作) 什么是 ...
- ISO9126软件质量模型
ISO9126软件质量模型,是评价软件质量的国际标准.6个特性27个子特性组成. ISO/IEC9126软件质量模型是一种评价软件质量的通用模型,包括3个层次: 1.质量特性 2.质量子特性 3.度量 ...
- SQLite数据操作
1.向学生表中插入100条数据 2.按条件查询学生数据 3.修改学生数据 4.删除学生数据 import UIKit class ViewController: UIViewController { ...
- KEIL与ADS1.2共存
出现的问题: 原来电脑已经安装了ADS1.2.现在安装keil5编译一个32位新唐单片机程序时,出现了如下错误: Error: L6411E: No compatible library exists ...
- beeline vs hive cli
近期,大数据开发环境升级为cloudera 5.3. 配套的hive版本升级为0.13.1.可以使用心仪已久的分析开窗函数了.但在使用的过程中发现一些问题,仅记于此. 1.在使用hive命令的时候,发 ...
- selenium更改readonly属性
1.用js实现 JavascriptExecutor removeAttribute = (JavascriptExecutor)dr; //remove readonly attrib ...
- CSS 实用技巧:制作三角形
实现如图所示的三角形图标: html代码如下: <div class="arrow-up"></div> <div class="arrow ...
- 实习小记-python 内置函数__eq__函数引发的探索
乱写__eq__会发生啥?请看代码.. >>> class A: ... def __eq__(self, other): # 不论发生什么,只要有==做比较,就返回True ... ...
- UESTC 883 方老师与两个串 --二分搜索+DP
CF原题 由题可知,n,m太大,无法开出dp[n][m]的数组. 观察发现s/e最大为300,也就是说,选用第一种操作的次数不会超过300. 于是定义dp[i][j],第一个串的前i个数,使用了j次第 ...