关于数据推送,传统方法是前端(不)定时发送HTTP请求进行轮询。但这种方式非常的损耗服务器资源,不适合访问量高的情况。
目前H5提供两种方式:Server-Sent Events 和 WebSockets。 前者只是服务器单向推送数据,易于使用,且浏览器会自动重连;后者支持交互,但实现较复杂。 本文只介绍前一种方案。
###JavaScript API###
var source = new EventSource(URL); // 注意跨域问题
source.addEventListener('message', function(e) {
console.log(e.data);
}, false);
source.addEventListener('open', function(e) {
// Connection was opened.
}, false);
source.addEventListener('error', function(e) {
if (e.readyState == EventSource.CLOSED) {
// Connection was closed.
}
}, false);
连接成功后,浏览器每隔3秒会自动重连,收到的数据通过message事件响应。
###Event Stream数据格式###
服务器正常情况下返回一个Content-Type类型为text/event-stream的纯文本内容。
最简单形如:data:str\n\n,即以data:起头,两个换行符结尾。这样e.data就是str。
如果要返回多行文本,依样增加,但要注意前面只添加一个换行符,最后一个则是两个:
data: first line\n
data: second line\n\n
如果要返回JSON格式的内容呢?依法炮制:
data: {\n
data: "msg": "hello world",\n
data: "id": 12345\n
data: }\n\n
为了标记响应数据,可以增加一段id: 12345\n,id值可以通过message响应事件的e.lastEventId属性读取。同时,浏览器发送请求时,其消息头会自动带上这个数值(参数名为Last-Event-ID)。
有时候数据更新比较缓慢,因此设置WEB延迟一段事件再发送请求,方法是增加一个retry属性:
retry: 10000\n
data: hello world\n\n
这样下一次请求会延长到10秒。仅一次有效。
甚至,你还可以自定义添加事件名称(默认是message):
// 服务器端
data: {"msg": "First message"}\n\n
event: userlogon\n
data: {"username": "John123"}\n\n
event: update\n
data: {"username": "John123", "emotion": "happy"}\n\n
// WEB端
source.addEventListener('message', function(e) {
var data = JSON.parse(e.data);
console.log(data.msg);
}, false);
source.addEventListener('userlogon', function(e) {
var data = JSON.parse(e.data);
console.log('User login:' + data.username);
}, false);
source.addEventListener('update', function(e) {
var data = JSON.parse(e.data);
console.log(data.username + ' is now ' + data.emotion);
}, false);
###取消或中断连接###
在WEB端,通过source.close()关闭连接。
在服务器端,返回一个Content-Type非text/event-stream或HTTP status不为200的应答即可。
参考: