在前端开发中,我们经常需要实时向服务器请求数据并更新页面。传统方式是使用 Ajax 轮询,即每隔一段时间向服务器发送一次请求,从而获取数据。然而,这种方式会占用大量带宽和服务器资源,降低性能。为了解决这个问题,我们可以使用 Server-sent Events(SSE)。
什么是 Server-sent Events(SSE)
Server-sent Events 是一种 HTML5 新特性,用于实现服务器向客户端推送数据,是一种单向实时通信方式。它基于 HTTP 协议,服务器端可以向客户端单向发送消息,并在客户端处接收这些消息。
使用 Server-sent Events,我们可以轻松地实现服务器向客户端的长连接,从而消除了 Ajax 轮询所带来的性能问题。
使用 Server-sent Events
在使用 Server-sent Events 之前,我们需要先了解一下事件流概念。
- eventsource:客户端和服务器之间的连接,由它向客户端发送消息。
- event: 用于发送消息,每个消息包含一个事件类型和数据,格式如下:
event: event-type data: payload
- id: 可选的,表示此消息的编号,用于维持消息的顺序,格式如下:
id: message-id event: event-type data: payload
通过这些概念,我们可以开始使用 Server-sent Events。
服务器端代码
下面是一个使用 Node.js 的 SSE 服务端示例代码,该代码通过 Express 框架创建了一个 HTTP 服务,然后使用 SSE 向客户端发送数据。
const express = require('express'); const { EventEmitter } = require('events'); const app = express(); app.get('/event-stream', (req, res) => { // 设置 Content-Type 为 text/event-stream res.set('Content-Type', 'text/event-stream'); // 设置允许跨域访问 res.set('Access-Control-Allow-Origin', '*'); // 设置不使用缓存 res.set('Cache-Control', 'no-cache'); // 创建一个 EventEmitter 实例 const eventEmitter = new EventEmitter(); // 模拟发送 10 次消息 let count = 0; const intervalId = setInterval(() => { if (count >= 10) { // 发送完毕 clearInterval(intervalId); res.end(); eventEmitter.removeAllListeners(); } else { // 发送消息 res.write(`event: message\n`); res.write(`data: ${JSON.stringify({ message: `message-${count}` })}\n\n`); count++; } }, 1000); // 注册关闭事件 req.on('close', () => { clearInterval(intervalId); eventEmitter.removeAllListeners(); }); }); const port = 3000; app.listen(port, () => { console.log(`Server is listening on port ${port}`); });
上述代码使用 set
方法设置响应的头部信息,然后创建了一个 EventEmitter 实例,模拟向客户端发送 10 次消息,并在最后一次发送完毕后结束 HTTP 连接。同时还注册了 close
事件,用于在客户端关闭连接时停止消息的发送。
客户端代码
下面是一个使用纯 JavaScript 的 SSE 客户端示例代码,该代码向指定 URL 发送 Server-sent Events 请求,并接收从服务器端推送过来的消息。
const eventSource = new EventSource('/event-stream'); eventSource.onopen = () => { console.log('SSE connection has been opened'); }; eventSource.onerror = (e) => { if (e.readyState === EventSource.CLOSED) { console.log('SSE connection has been closed'); } else { console.error('SSE error:', e); } }; eventSource.addEventListener('message', (e) => { console.log('SSE message:', JSON.parse(e.data)); });
上述代码通过创建一个 EventSource
对象,向服务器端的 /event-stream
URL 发送请求,并在收到消息时打印消息。
SSE 的优点
使用 Server-sent Events 与传统的 Ajax 轮询相比,有以下优点:
- 减少带宽占用和服务器资源消耗:因为 SSE 是一种单向通信方式,只有服务器向客户端发送消息,客户端不需要向服务器发送请求,从而减少了带宽占用和服务器资源消耗。
- 实时性更好:因为 SSE 是基于长连接的,客户端与服务器端之间的连接保持打开状态,服务端可以随时向客户端发送消息,从而实现实时更新。
- 可靠性更高:因为 SSE 可以自动重连,客户端与服务器之间的连接在中途断开后可以自动恢复,从而提高了可靠性。
总结
本文介绍了使用 Server-sent Events 的方法,并提供了一个示例代码。相比传统的 Ajax 轮询,使用 Server-sent Events 可以减少带宽占用和服务器资源消耗,同时提高实时性和可靠性。如果你想使用 SSE 实现实时更新,那么本文所提供的示例代码可以为你提供一个很好的起点。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6595570eeb4cecbf2d98537c