什么是SSE?
SSE全称为Server Send Event,顾名思义服务器发送事件。严格地说,HTTP 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息(streaming)。
也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。本质上,这种通信就是以流信息的方式,完成一次用时很长的下载。
SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 HTTP 协议,目前除了 IE/Edge,其他浏览器都支持。
SSE的用法
1. 客户端
使用SSE时,首先在客户端生成一个EventSource对象,向服务器发起连接
var source = new EventSource(url)
连接建立之后,就会调用下面的方法
source.onopen=function(event){
//...
}
//另一种写法
source.addListener('open',functin(event){
//...
}
客户端收到服务器消息就会触发message事件
source.onmessage=function(event){
console.log(event.data)
}
出现通信错误就会触发error事件
source.onerror=funtion(event){
console.log(event)
}
自定义事件
source.addListener('foo',function(event){
//...
}
上面代码中,浏览器对 SSE 的foo事件进行监听。
2. 服务器
服务器向浏览器发送的 SSE 数据,必须是 UTF-8 编码的文本,具有如下的 HTTP 头信息。
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
每一次发送的信息,由若干个message组成,每个message之间用\n\n分隔。每个message内部由若干行组成,每一行都是如下格式。
[field]: value\n
上面的field可以取四个值。
data//表示数据内容
event//表示事件
id//代表数据标识
retry//表示重连时间
node使用例子
var http = require("http");
http.createServer(function (req, res) {
var fileName = "." + req.url;
if (fileName === "./stream") {
res.writeHead(200, {
"Content-Type":"text/event-stream",
"Cache-Control":"no-cache",
"Connection":"keep-alive",
"Access-Control-Allow-Origin": '*',
});
res.write("retry: 10000\n");
res.write("event: connecttime\n");
res.write("data: " + (new Date()) + "\n\n");
res.write("data: " + (new Date()) + "\n\n");
interval = setInterval(function () {
res.write("data: " + (new Date()) + "\n\n");
}, 1000);
req.connection.addListener("close", function () {
clearInterval(interval);
}, false);
}
}).listen(8844, "127.0.0.1");
在nextjs中使用需要注意
- 客户端无法接收到数据,需要如下设置
async function handler(req: NextApiRequest, res: NextApiResponse){
res.setHeader('Content-Type', 'text/event-stream;charset-utf-8');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('X-Accel-Buffering', 'no');
res.setHeader('Cache-Control', 'no-cache, no-transform');
}
主要是设置'no-cache, no-transform',因为nextjs默认会压缩内容。
- 客户端无法收到data中的换行符,解决办法是对于有空格符的消息添加自定义事件,客户端监听进行空格符的添加