使用 SSE 实现聊天室的实时消息推送
随着移动互联网的普及,实时消息推送已成为网页应用开发的必备功能之一。传统的轮询方式会导致大量无效的请求,对服务器造成压力,并且消息的实时性无法保障。而 SSE(Server-sent Events)技术可以实现服务器主动向客户端推送消息,避免了不必要的网络请求和服务器压力,同时也保证了消息的实时性。
本文将介绍如何使用 SSE 技术实现聊天室的实时消息推送,并提供详细的代码示例供读者参考和学习。
- SSE 技术介绍
SSE(Server Sent Events)是一种在 Web 浏览器中向客户端推送事件的技术。它的原理是客户端通过 HTTP 连接不断接收服务器发送过来的数据,从而实现双向通信。SSE 的主要特点如下:
(1)SSE 是一种纯文本协议,不需要像 WebSocket 一样进行握手等复杂的协议处理。
(2)SSE 不需要借助外部插件,浏览器对 SSE 的支持较好,目前绝大部分现代浏览器(包括 IE)都已经支持了 SSE。
(3)SSE 使用单个 HTTP 连接,避免了频繁建立和断开连接所带来的性能损失。
(4)SSE 可以支持自定义事件类型和自定义数据格式,具有很大的灵活性。
- SSE 的应用场景
SSE 主要适用于需要实现实时回调和推送的应用场景,如在线聊天室、实时监控等等。特别是那些需要推送的数据量不大,且要求实时性较高的场景。
- 使用 SSE 实现聊天室的实时消息推送
下面以实现一个简单的聊天室为例,详细介绍如何使用 SSE 实现实时消息推送功能。
3.1 服务端代码
服务端是一个简单的 Node.js 应用程序,使用 Express 框架开发,它的核心代码如下:
// javascriptcn.com 代码示例 const express = require('express'); const bodyParser = require('body-parser'); const app = express(); const messages = []; // 处理请求体的 JSON 格式数据 app.use(bodyParser.json()); // 发送消息到聊天室 app.post('/message', (req, res) => { const message = req.body.message; console.log(`message ${message}`); messages.push(message); res.send('OK'); }); // SSE 接口 app.get('/stream', (req, res) => { console.log(`SSE connected.`); res.setHeader('Content-Type', 'text/event-stream'); res.writeHead(200, { 'Connection': 'keep-alive', 'Cache-Control': 'no-cache' }); const id = Date.now(); res.write(`id: ${id}\n`); res.write(`event: init\n`); res.write(`data: ${JSON.stringify(messages)}\n\n`); const intervalID = setInterval(() => { res.write(`id: ${id}\n`); res.write(`event: message\n`); res.write(`data: ${JSON.stringify(messages)}\n\n`); }, 1000); req.on('close', () => { console.log(`SSE closed.`); clearInterval(intervalID); }); }); app.use(express.static('public')); app.listen(3000, () => console.log(`Chat app listening on port 3000!`));
以上代码实现了两个接口:
(1)POST /message:接收客户端发送的消息,并将其保存在一个数组中。
(2)GET /stream:使用 SSE 技术向客户端推送消息。在连接建立后,服务端会先发送一个 init 事件,将已保存的消息数据发送给客户端。之后,服务端会使用 setInterval 定时向客户端发送消息。
以上代码处理比较简单,主要注意点如下:
(1)使用 res.setHeader('Content-Type', 'text/event-stream') 设置响应头,告诉浏览器返回的是 SSE 数据。
(2)使用 setInterval 定时向客户端发送消息,注意在每次发送前要先发送一个 id 字段,用于确保每次发送的消息都是唯一的。
(3)使用 req.on('close', () => {}) 监听连接关闭事件,当 SSE 连接关闭时,清除定时器。
3.2 客户端代码
客户端代码主要是一个简单的 HTML 页面和 JavaScript 脚本,核心代码如下:
// javascriptcn.com 代码示例 // 初始化 SSE 连接 const source = new EventSource('/stream'); source.addEventListener('init', function (e) { const data = JSON.parse(e.data); data.forEach((message) => { displayMessage(message); }); }, false); // 接收到新消息时的处理函数 source.addEventListener('message', function (e) { const data = JSON.parse(e.data); data.forEach((message) => { displayMessage(message); }); }, false); // 发送消息到聊天室 document.querySelector('#submit-btn').addEventListener('click', function (e) { const message = document.querySelector('#input-text').value; fetch('/message', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: message }) }); document.querySelector('#input-text').value = ''; }); // 将消息显示在聊天室中 function displayMessage(message) { const li = document.createElement('li'); li.appendChild(document.createTextNode(message)); document.querySelector('#message-list').appendChild(li); }
客户端代码比较简单,主要实现以下功能:
(1)通过 new EventSource('/stream') 创建 SSE 连接,监听服务器推送过来的事件。
(2)在接收到服务器的 init 事件时,将已保存的消息数据显示在聊天室中。
(3)在接收到服务器的 message 事件时,将新增的消息数据显示在聊天室中。
(4)提交聊天消息时,向服务器发送 POST 请求,将消息数据保存在服务器端。
3.3 参考资料
以上代码示例只是一个简单的实现,其中还有很多优化的空间,读者可以参考下面的资料进一步学习和了解 SSE 技术的使用。
(1)MDN Server-Sent Events 教程:https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
(2)深入浅出 Server-Sent Events:https://funteas.com/topic/5b30841073337f2f2ff85145
(3) Node.js SSE 模块:https://www.npmjs.com/package/sse-express
- 总结
本文详细介绍了使用 SSE 实现聊天室的实时消息推送,并提供了完整的服务端和客户端代码示例。通过学习和实践 SSE 技术,我们可以更加高效地处理实时消息推送等应用场景,提高网络应用程序的性能和用户体验。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65855c49d2f5e1655d0025f4