什么是JavaScript中的服务器发送事件?
在 Web 应用程序开发中,经常需要将服务器上的数据实时显示在客户端上。以往的做法是轮询,在客户端不断地向服务器发送请求,服务器返回数据,这样会占用大量的带宽和服务器资源。然而,现在有一个更好的解决方案——服务器发送事件(Server-Sent Events,简称 SSE)。
服务器发送事件(SSE)机制是一种基于HTTP协议的服务器推送技术。它允许服务器向客户端推送任意数量的消息,从而能够实现服务器主动推送数据到客户端的效果。SSE 常用于实时性要求较高的应用场景,如股票交易、拍卖等,通常被认为是 WebSocket 技术的一种替代方案,使用 SSE 比使用 WebSocket 更加轻量级。
SSE 与 WebSocket 不同,SSE 采用的是单向通信的方式。当客户端向指定的 URL 发送一个 SSE 请求时,浏览器会在建立连接之后一直等待直到服务器发送一条消息为止。这种方式避免了 WebSocket 的双向通信所引发的一些安全问题,并且不需要额外的握手流程,可以快速地建立连接和传输数据。
SSE 的用法
使用 SSE 需要借助一个新的浏览器 API:EventSource,它定义了与服务器建立 SSE 连接的方法。
要建立 SSE 连接,只需要在客户端代码中创建一个 EventSource 对象,然后调用它的 open
方法,传入一个服务器地址作为参数:
const source = new EventSource('/sse')
如果服务器设置了 CORS(跨域资源共享)响应头,那么需要将 EventSource
构造函数的第一个参数设置为完整的 URL 。在服务器端,需要监听请求的 URL,并向客户端发送 SSE 事件。下面是一个简单的 Node.js 例子,监听 /sse
路径的 GET 请求,并且每秒钟向客户端推送一条消息:
const http = require('http')
const server = http.createServer((req, res) => {
if (req.url === '/sse') {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
})
let id = 0
setInterval(() => {
res.write(`id: {id}\n`)
res.write(`data:{new Date().toISOString()}\n\n`)
id++
}, 1000)
} else {
res.writeHead(404)
res.end()
}
})
server.listen(3000, () => {
console.log('Server is listening on http://localhost:3000')
})
上面的代码使用了 setInterval
方法每秒钟向客户端推送一条消息,由于 SSE 是单向通信,因此只需要将消息以特定格式发送给客户端即可。
在客户端,可以监听 EventSource 对象的 message
事件,当服务器向客户端发送消息时,会触发该事件:
source.onmessage = event => {
console.log(event.data)
}
event.data
属性包含服务器发送的数据。SSE 支持多种类型的消息,例如:普通文本、JSON、HTML 等。
当客户端与服务器的 SSE 连接发生错误时,会触发 EventSource 对象的 error
事件。通过该事件的 event.target.readyState
属性可以获取当前连接的状态:
0
:连接已经关闭。1
:正在连接。2
:已经建立连接,可以接收服务器发送的数据。
与 XMLHttpRequest
对象不同,EventSource对象支持重连机制,当连接断开时,浏览器会自动发起新的连接请求。可以通过 EventSource.retry
属性来控制重连策略,例如:
const source = new EventSource('/sse')
source.retry = 3000 // 每隔 3 秒尝试重新连接一次
SSE 的优点
相对于轮询、Comet 等技术,SSE 有以下几点优点:
- 省去了客户端不断向服务器发送请求的过程,减少带宽和服务器资源的损耗。
- SSE 与 WebSocket 相比,SSE 协议更加轻量级。不需要进行复杂的握手流程,可以快速建立连接和传输数据。
- SSE 可以支持自定义事件、重连机制、超时机制等丰富的特性。
- SSE 提供了对跨域请求的支持,可以安全地将信息发送给任何站点,而不必担心安全问题。
SSE 的缺点
尽管 SSE 提供了一种实时推送数据的便捷方式,但是它的缺点也是存在的:
- SSE 采用的单向通信方式,只能从服务器向客户端发送数据,不支持双向通信。
- SSE 的兼容性在一定程度上依赖于浏览器。虽然现代浏览器基本上都支持 SSE,但是特定的浏览器和版本可能不支持 SSE。
结论
SSE 是一种比较新的服务器推送技术,与传统的轮询方式相比,SSE 更加高效,并且可以实现实时推送数据的需求。相对于 WebSocket 技术而言,SSE 的协议更加轻量级,适用于一些不需要复杂的双向通信的应用场景。虽然 SSE 的兼容性存在一定问题,但是该技术在开发实时应用时还是值得考虑的。