Server-Sent Events (SSE) 是一种在 Web 应用程序中保持连接的技术,它允许服务器向客户端推送事件,而无需客户端发出请求。它是一种基于 HTTP 的协议,与 WebSocket 不同,它只允许服务器向客户端发送数据,而不允许双向通信。
SSE 的优势在于它可以实现实时通信,而且相对于 WebSocket 更加轻量级,因为它不需要建立双向通信的通道。它适用于那些需要实时更新数据的应用程序,例如股票报价、即时通讯等。
SSE 的工作原理
SSE 是基于 HTTP 的协议,因此它使用 HTTP 连接与服务器通信。客户端向服务器发出一个 HTTP 请求,服务器将响应该请求并保持连接打开。一旦连接打开,服务器就可以向客户端发送事件,而客户端可以通过监听事件来获取数据。
在 SSE 中,服务器发送的数据被称为事件(event),它由一个事件类型和一个事件数据组成。事件类型是一个字符串,用于标识事件的类型,而事件数据可以是任何有效的文本数据。
客户端可以通过 EventSource 对象来监听事件,它会自动处理服务器发送的事件。当服务器发送一个事件时,EventSource 对象会触发一个事件,客户端可以在该事件中获取事件类型和数据。
SSE 的使用
SSE 的使用非常简单,只需要在客户端创建一个 EventSource 对象,然后指定服务器的 URL 即可。服务器需要发送一些事件来与客户端通信。
下面是一个简单的 SSE 示例:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>SSE 示例</title> </head> <body> <h1>服务器时间</h1> <div id="time"></div> <script> var eventSource = new EventSource('/sse'); eventSource.addEventListener('time', function(event) { var time = event.data; document.getElementById('time').innerHTML = time; }, false); </script> </body> </html>
在上面的示例中,我们创建了一个 EventSource 对象,并将服务器的 URL /sse
作为参数传递给它。服务器会定期发送一个名为 time
的事件,事件数据是服务器的当前时间。客户端监听 time
事件,并将事件数据显示在页面上。
服务器端的代码如下:
const http = require('http'); http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); setInterval(() => { res.write(`event: time\ndata: ${new Date().toLocaleString()}\n\n`); }, 1000); }).listen(8080);
在上面的代码中,我们创建了一个 HTTP 服务器,并在每秒钟向客户端发送一个名为 time
的事件,事件数据是服务器的当前时间。注意到我们设置了响应头 Content-Type
为 text/event-stream
,这是 SSE 的标准 MIME 类型。
SSE 的注意事项
虽然 SSE 看起来非常简单,但是在实际使用中需要注意一些问题。
首先,SSE 使用的是长轮询(long-polling)技术,因此它可能会导致服务器的负载增加。为了避免这个问题,服务器可以通过设置响应头 Cache-Control: no-cache
来禁用缓存,从而避免客户端发出不必要的请求。
其次,SSE 的事件数据必须是有效的文本数据,不能是二进制数据。如果需要发送二进制数据,可以使用 Base64 编码将其转换为文本数据。
最后,SSE 并不是所有浏览器都支持。虽然大多数现代浏览器都支持 SSE,但是一些老旧的浏览器可能无法支持它。如果需要兼容老旧的浏览器,可以考虑使用其他技术,例如轮询或 WebSocket。
总结
本文介绍了 SSE 技术,它是一种在 Web 应用程序中保持连接的技术,可以实现实时通信。我们讨论了 SSE 的工作原理、使用方法以及注意事项。虽然 SSE 看起来非常简单,但是在实际使用中需要注意一些问题。如果您需要实现实时通信的功能,可以考虑使用 SSE。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65899cc6eb4cecbf2def238f