Skip to content
导航

EventSource

概念

SSE(Server-sent events)服务器发送事件,主要是客户端用到 EventSource API

EventSource 是兼容性比 WebSocket 更好的浏览器API

与 WebSocket 不同的是,EventSource 是单向的。数据只能从服务端到发送到客户端

Node.js 服务端

实现EventSource连接就是,服务器向客户端声明,接下来要发送的是流信息(streaming)

也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。
客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。
本质上,这种通信就是以流信息的方式,完成一次用时很长的下载。

服务端按如下响应,就能满足与客户端建立EventSource连接

js
response.writeHead(200, {
  "Content-Type":"text/event-stream",
  "Cache-Control":"no-cache",
  "Connection":"keep-alive",
  "Access-Control-Allow-Origin": '*',
});

response.write(`retry: 10000\n`)
response.write(`
id: test
event: custom-event
data: ${new Date()}\n
`)

// event-stream 连接会保持,每次写入的数据会被客户端接收

事件流格式规范

4个有效字段,其他会被忽略

  • retry:设置连接断开后,客户端自动重连的时间间隔。设置非整数无效
  • id:事件 ID,客户端通过lastEventId读取
  • event:事件类型,默认为message
  • data:事件的数据字段

消息与消息间通过空行区分,没有空行会合并消息

js
`
data: {
data: "foo": "bar",
data: "baz", 555
data: }
`
//  { "foo": "bar", "baz", 555 }

客户端

浏览器提供全局API EventSource 构造函数方便建立连接

js
const evtSource = new EventSource("http://localhost:9000")
console.log(evtSource.readyState); // 0

evtSource.addEventListener('open', function(){
  console.log(evtSource.readyState); // 1
})

evtSource.addEventListener('message', function(event){
  console.log(event.data) //没有 `event` 或 `event: message` 消息会在这里接收
})

evtSource.addEventListener('custom-event', function(){
  console.log(event.data) //`event: custom-event` 消息会在这里接收
  console.log(event.lastEventId) // 'test'
})

evtSource.addEventListener('error', function(){
  evtSource.close() // 关闭连接,不关闭会自动重连
  console.log(evtSource.readyState); // 2
})

参考资料