在现代 Web 应用中,大规模数据推送是一个常见的需求。例如,我们可能需要实时更新股票行情、天气预报、即时聊天等场景。为了实现这些实时数据推送,我们可以使用 Server-sent Events (SSE) 技术。
什么是 Server-sent Events?
Server-sent Events 是一种基于 HTTP 的实时通信技术,它允许服务器向客户端发送事件,而无需客户端发起请求。与 WebSocket 相比,SSE 更加轻量级,适用于一些简单的实时通信场景。
SSE 的工作原理是,客户端向服务器发送一个 HTTP 请求,请求头中包含了 Accept: text/event-stream
。服务器在收到请求后,会保持连接不断开,并向客户端发送事件。事件使用纯文本格式,以 event: eventName
开头,后面跟着 data: eventData
。例如:
event: update data: {"name": "John", "age": 30}
客户端可以通过 JavaScript 监听 EventSource
对象的 message
事件,来接收服务器发送的事件。例如:
const eventSource = new EventSource('/stream'); eventSource.addEventListener('update', event => { const data = JSON.parse(event.data); console.log(data); });
如何使用 SSE 实现大规模数据推送?
使用 SSE 实现大规模数据推送的基本思路是,服务器向所有客户端发送相同的事件。为了实现这个功能,我们需要使用一些技巧。
首先,我们需要将所有客户端的连接都保存起来。当有新的数据需要推送时,我们可以遍历所有连接,向它们发送相同的事件。这个功能可以使用 Node.js 的 net
模块实现。例如:
// javascriptcn.com 代码示例 const connections = new Set(); const server = net.createServer(socket => { connections.add(socket); socket.on('close', () => { connections.delete(socket); }); }); function broadcast(eventName, eventData) { for (const socket of connections) { socket.write(`event: ${eventName}\ndata: ${JSON.stringify(eventData)}\n\n`); } }
接下来,我们需要将 SSE 和 HTTP 结合起来。我们可以使用 Express 框架来实现这个功能。例如:
// javascriptcn.com 代码示例 const app = express(); app.get('/stream', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); const socket = new net.Socket(); socket.connect({port: 8080}, () => { socket.on('data', data => { res.write(data); }); }); req.on('close', () => { socket.destroy(); }); });
最后,我们需要在客户端上监听 SSE 事件,并处理它们。例如:
const eventSource = new EventSource('/stream'); eventSource.addEventListener('update', event => { const data = JSON.parse(event.data); console.log(data); });
总结
使用 Server-sent Events 技术可以实现大规模数据推送,它具有轻量级、易于实现等优点。在实现大规模数据推送时,我们需要将所有客户端的连接都保存起来,并向它们发送相同的事件。在客户端上,我们需要使用 EventSource
对象来监听 SSE 事件,并处理它们。
示例代码:https://github.com/LingDong-/sse-example
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/655694a8d2f5e1655d10271d