什么是JavaScript中的服务器发送事件?

什么是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 的兼容性存在一定问题,但是该技术在开发实时应用时还是值得考虑的。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程