【总结】HTML5之EventSource专题


1    简介

HTML5 服务器发送事件(server-sentevent)允许网页获得来自服务器主动推送的更新。

EventSource接口用来管理服务器发送事件.你可以通过将EventSource对象的onmessage属性指向一个自定义方法来处理那些从服务器接受到的无类型的消息(也就是,没有event字段的消息).你还可以使用addEventListener()方法来监听其他指定了事件类型的消息。

1.1    Server-Sent 事件 - 单向消息传递

Server-Sent 事件指的是网页自动获取来自服务器的更新。以前也可能做到这一点,前提是网页不得不询问是否有可用的更新。通过服务器发送事件,更新能够自动到达。

例子:Facebook/Twitter 更新、估价更新、新的博文、赛事结果等。

 

1.2    浏览器兼容性

所有主流浏览器均支持服务器发送事件,除了Internet Explorer。

 

1.2.1 Desktop

Feature

Chrome

Firefox (Gecko)

Internet Explorer

Opera

Safari

EventSource support

9

6.0 (6.0)

?

11

5

Cross-Origin Resource Sharing
support

26

11.0 (11.0)

?

12

?

 

1.2.2 Mobile

 

Feature

Android

Firefox Mobile (Gecko)

IE Mobile

Opera Mobile

Safari Mobile

EventSource support

?

?

?

?

?

 

 

1.3    接收 Server-Sent 事件通知

EventSource 对象用于接收服务器发送事件通知:

1.3.1 客户端实例

var source=new EventSource("demo_sse.php");

source.onmessage=function(event)

{

          document.getElementById("result").innerHTML+=event.data+ "
";

};

 

例子解释:

l   创建一个新的EventSource 对象,然后规定发送更新的页面的 URL(本例中是 "demo_sse.php")

l   每接收到一次更新,就会发生onmessage 事件

l   当 onmessage 事件发生时,把已接收的数据推入 id 为 "result" 的元素中

 

1.3.2 服务器端代码实例

服务器端事件流的语法是非常简单的。把"Content-Type" 报头设置为 "text/event-stream"。现在,您可以开始发送事件流了。

 

PHP 代码 (demo_sse.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 代码 (VB) (demo_sse.asp):

<%

Response.ContentType="text/event-stream"

Response.Expires=-1

Response.Write("data:" & now())

Response.Flush()

%>

 

代码解释:

l   把报头"Content-Type" 设置为 "text/event-stream"

l   规定不对页面进行缓存

l   输出发送日期(始终以"data: " 开头)

l   向网页刷新输出数据

 

2    EventSource 对象

2.1    方法

void close();

void init(in nsIPrincipal principal, innsIScriptContext scriptContext, in nsPIDOMWindow ownerWindow, in DOMStringurl);

2.1.1  close()

如果连接处于打开状态,则关闭连接,并把readyState属性的值设置为CLOSED.如果连接已经关闭,则该方法不会做任何事情.

 

2.2    init

 

C++代码中新建一个EventSource对象.

void init(   in nsIPrincipal principal,   in nsIScriptContext scriptContext,   in nsPIDOMWindow ownerWindow,   in DOMString url );

2.2.1 参数

principal                                                              

用来进行该请求的principal,不能为null.

scriptContext                                                  

进行该请求的脚本上下文,可以为null.

ownerWindow                                      

与该请求关联的window对象,可以为null.

url                                                                                                  

EventSource对象的目标URL,不能为空.

 

 

 

 

2.3    属性

 

属性名

类型

描述

onerror

nsIDOMEventListener

初始值为null,需要指向一个自定义函数,在连接发生错误的时候会自动调用那个自定义函数.

onmessage

nsIDOMEventListener

初始值为null,需要指向一个自定义函数,在接受到一个没有event字段的消息时会自动调用那个自定义函数.

onopen

nsIDOMEventListener

初始值为null,需要指向一个自定义函数,在成功建立连接后调用.

readyState

long

连接的当前状态,必须为CONNECTING,OPEN,或者CLOSED中的一种只读.

url

DOMString

只读.

 

除了这些普通属性,下面还有两个无法通过JavaScript代码直接访问的内部属性(当然,没有常规的属性名):

重新连接时间

一个时间值,单位为毫秒,用来决定在连接失败后需要等待多久再次尝试连接.

最后一次的事件ID字符串

初始值为空字符串,如果服务器发送的消息中包含有id字段,则对应的字段值会赋值给该属性.如果该属性已经有值,则会覆盖旧的那个值.

 

2.4    常量

 

常量名

描述

CONNECTING

0

正在建立连接.

OPEN

1

连接处于打开状态,正在调度事件.

CLOSED

2

连接没有被建立,或者已经关闭,或者发生了某个致命错误.

 

3    使用服务器发送事件

在Web应用程序中使用服务器发送事件很简单.在服务器端,只需要按照一定的格式返回事件流,在客户端中,只需要为一些事件类型绑定监听函数,和处理其他普通的事件没多大区别.

3.1    从服务器接受事件

    服务器发送事件API也就是EventSource接口,在你创建一个新的EventSource对象的同时,你可以指定一个接受事件的URI.例如:

var evtSource = new EventSource("ssedemo.php");

注:从Firefox 11开始,EventSource开始支持CORS. 虽然该特性目前并不是标准, 但很快会 成为标准.

 

一旦你成功初始化了一个事件源,就可以开始监听它的消息了:

3.1.1 利用onmessage监听消息

evtSource.onmessage =function(e){  

var newElement = document.createElement("li");     

newElement.innerHTML ="message: "+ e.data;       

eventList.appendChild(newElement);

}

上面的代码监听了那些从服务器发送来的所有没有指定事件类型的消息(没有event字段的消息),然后把消息内容显示在页面文档中.

3.1.2 使用addEventListener()方法来监听

    你也可以使用addEventListener()方法来监听其他类型的事件:

evtSource.addEventListener("ping",function(e){  

var newElement = document.createElement("li");     

var obj = JSON.parse(e.data);  

newElement.innerHTML ="ping at "+ obj.time;  

eventList.appendChild(newElement);},

false);

    这段代码也类似,只是只有在服务器发送的消息中包含一个值为"ping"event字段的时候才会触发对应的处理函数,也就是将data字段的字段值解析为JSON数据,然后在页面上显示出所需要的内容.

 

3.2    服务器端如何发送事件流

 服务器端发送的响应内容应该使用值为"text/event-stream"MIME类型.这里有一个事件流文件的例子Event streamformat.

 

演示的PHP代码如下:

date_default_timezone_set("America/New_York");

header("Content-Type:text/event-stream\n\n"); 

$counter = rand(1, 10);

while (1) {  

// Every second, sent a "ping"event.     

echo "event: ping\n";  

$curDate = date(DATE_ISO8601);  

echo 'data: {"time": "' .$curDate . '"}';  

echo "\n\n";     

// Send a simple message at randomintervals.     

$counter--;     

if (!$counter) {    

    echo'data: This is a message at time ' .

    $curDate. "\n\n";    

    $counter = rand(1, 10);  

}     

ob_flush();  

flush();  

sleep(1);

}

    上面的代码会让服务器每隔一秒生成一个事件流并返回,其中每条消息的事件类型为"ping",数据字段都使用了JSON格式,数组字段中包含了每个事件流生成时的时间字符串.而且会随机返回一些无事件类型的消息.

3.3    事件流格式

事件流仅仅是一个简单的文本数据流,文本应该使用UTF- 8格式的编码.每条消息后面都由一个空行作为分隔符.以冒号开头的行为注释行,会被忽略.

 

注:注释行可以用来防止连接超时,服务器可以定期发送消息一条注释行,以保持连接不断.

 

每条消息是由多个字段组成的,每个字段由字段名,一个冒号,以及字段值组成.

 

3.3.1字段

规范中规定了下面这些字段:

event

事件类型.如果指定了该字段,则在客户端接收到该条消息时,会在当前的EventSource对象上触发一个事件,事件类型就是该字段的字段值,你可以使用addEventListener()方法在当前EventSource对象上监听任意类型的命名事件, 如果该条消息 没有event字段,则会触发onmessage属性上的事件处理函数.

data

消息的数据字段.如果该条消息包含多个data字段,则客户端会用换行符把它们连接成一个字符串来作为字段值.

id

事件ID,会成为当前EventSource对象的内部属性"最后一个事件ID"的属性值.

retry

一个整数值,指定了重新连接的时间(单位为毫秒),如果该字段值不是整数,则会被忽略.

除了上面规定的字段名,其他所有的字段名都会被忽略.

注: 如果一行文本中不包含冒号,则整行文本会被解析成为字段名,其字段值为空.

 

3.3.2例子

3.3.2.1未命名事件

下面的例子中发送了三条消息,第一条仅仅是个注释,因为它以冒号开头.第二条消息只包含了一个data字段,值为"some text".第三条消息包含的两个data字段会被解析成为一个字段,值为"another message\nwith two lines".其中每两条消息之间是以一个空行为分割符的.

: this is a test stream  
data: some text  
data: another message 
data: with two lines

3.3.2.2  命名事件

下面的事件流中包含了一些命名事件.每个事件的类型都是由event字段指定的,另外每个data字段的值可以使用JSON格式,当然也可以不是.

event: userconnect 
data: {"username": "bobby", "time": "02:33:48"}  
event: usermessage 
data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}  
event: userdisconnect 
data: {"username": "bobby", "time": "02:34:23"}  
event: usermessage 
data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."}

3.3.2.3  混合两种事件

你可以在一个事件流中同时使用命名事件和未命名事件.

event: userconnect 
data: {"username": "bobby", "time": "02:33:48"}  
data: Here's a system message of some kind that will get used 
data: to accomplish some task.  
event: usermessage 
data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}

 

3.4        浏览器兼容性

3.4.1 Desktop

Feature

Chrome

Firefox (Gecko)

Internet Explorer

Opera

Safari

EventSource support

9

6.0 (6.0)

Not supported

11

5

 

3.4.2 Mobile

Feature

Android

Firefox Mobile (Gecko)

IE Mobile

Opera Mobile

Safari Mobile

EventSource support

Not supported

?

?

11.1

4

 

 

 

4    参考链接

HTML 5 服务器发送事件

http://www.w3school.com.cn/html5/html_5_serversentevents.asp

 

Server-Sent Events

http://www.w3.org/TR/eventsource/#the-eventsource-interface

 

使用服务器发送事件

https://developer.mozilla.org/zh-CN/docs/Server-sent_events/Using_server-sent_events

 

 

你可能感兴趣的:(编程日志,html5,enventsource)