随着移动互联网和社交媒体的飞速发展,实时聊天成为了越来越多网站和应用必不可少的功能之一。而 SSE (Server-Sent Events) 就是其中一种实现实时聊天的方式,它可以让服务器主动向客户端推送数据,没有轮询和刷新的过程,能够有效地减少网络传输量和服务器压力,同时也提高了用户体验。
本文将详细介绍利用 SSE 实现实时聊天的最佳实践,并附带示例代码和详细的指导意义,帮助前端开发者了解 SSE 技术的应用,并能够快速地在自己的项目中应用该技术。
SSE 的基本原理
SSE 是基于 HTTP 协议的,它利用了浏览器对于 HTTP 协议“流”的支持。当浏览器向服务器发送一个 SSE 请求时,服务器可以将需要推送的数据发送给客户端,浏览器会保持连接状态,直到服务器关闭连接或超时,就像与服务器一直保持着一个 WebSocket 连接一样。在这个过程中,服务器可以随时向客户端推送消息。
SSE 的消息使用 plain text 或者 JSON 格式,格式如下:
data: <消息内容> event: <事件名称> id: <消息编号> retry: <重试时间间隔>
其中 data
是必须的 field,表示消息的主要文本内容;event
是可选的,表示事件的名称;id
是可选的,表示消息编号; retry
是可选的,表示重试时间间隔,即如果浏览器在指定时间内未收到服务器的响应,它会重新发送 SSE 请求。
SSE 的 JavaScript API 也非常简单,演示代码如下所示:
// javascriptcn.com 代码示例 var source = new EventSource('http://example.com/sse'); source.onopen = function(event) { console.log('连接已开启!'); }; source.onmessage = function(event) { console.log('收到消息:', event.data); }; source.onerror = function(event) { console.error('连接出错!'); };
当浏览器向 EventSource 订阅一个 SSE 事件源时,可以注册 onopen
、onmessage
和 onerror
三个事件。当连接建立成功时,onopen
事件会被调用;当收到服务器推送的消息时,onmessage
事件会被调用,并且 event.data
包含了消息的内容;当连接出现错误时,onerror
事件会被调用。
SSE 实现实时聊天的最佳实践
SSE 实时聊天的基本流程如下:
- 客户端向服务器发送 SSE 请求;
- 服务器监听客户端的 SSE 请求,并向其推送数据;
- 客户端通过 JavaScript API 监听服务器推送的消息,并在收到消息时更新 UI。
针对该流程,下面将介绍 SSE 实时聊天的最佳实践。
服务器端实现
为了方便起见,本文以 Node.js + Express 作为后端示例示例,实时聊天使用 Socket.io 实现。
首先,在服务器端建立一个 SSE 路由,处理客户端的 SSE 请求:
// javascriptcn.com 代码示例 // 引入 SSE 库 const sse = require('sse'); // 创建 SSE 路由 const sseRouter = express.Router(); sseRouter.get('/sse', (req, res) => { const es = new sse(req); // 准备 SSE 格式的消息 const message = { data: '欢迎来到 SSE 实时聊天!', event: 'welcome', id: '1' }; // 向客户端推送 SSE 消息 es.send(JSON.stringify(message)); // 监听客户端 SSE 连接,向其持续推送消息 setInterval(() => { const message = { data: '现在时间是 ' + new Date().toLocaleTimeString(), event: 'time', id: Date.now() }; es.send(JSON.stringify(message)); }, 1000); });
上述代码通过 sse
库创建了一个 SSE 路由,并在其 sse
路由上监听客户端的 SSE 请求。当有新的连接请求时,创建一个 EventSource
对象,并通过 send
方法向客户端推送第一条消息,接着通过 setInterval
持续向客户端推送消息。服务器通过定时器模拟发送多条聊天消息。
Socket.io 用于处理客户端与服务器之间的实时通信,需要在 sseRouter
路由中引入 Socket.io 并添加必要的监听器:
// javascriptcn.com 代码示例 // 引入 Socket.io 库 const socketIo = require('socket.io'); // 创建 Socket.io 服务器,并添加到 SSE 路由 const io = socketIo(server); sseRouter.io = io; io.on('connection', (socket) => { console.log('有一个新的客户端接入了!'); // 监听客户端发送的消息 socket.on('message', (message) => { console.log(`收到一条新消息:${message}`); // 模拟广播消息 io.emit('message', message); }); // 监听客户端断开连接事件 socket.on('disconnect', () => { console.log('客户端已断开连接!'); }); });
上述代码创建了 Socket.io 服务器,并将其添加到 SSE 路由中。当客户端连接上 Socket.io 服务器时(实际上已经在 SSE 路由中建立 SSE 连接),服务器会监听客户端发送的 message
事件,用于处理客户端发送的聊天消息。当服务器收到聊天消息后,调用 io.emit
方法广播消息,将消息发送给所有已连接的客户端。
到此为止,服务器端的实现就完成了。
客户端实现
接下来,针对上面服务器端的示例代码,介绍客户端的实现。HTML 结构如下:
// javascriptcn.com 代码示例 <div> <h2>SSE 实时聊天 Demo</h2> <div id="time"></div> <hr /> <ul id="messages"></ul> <form> <input id="message" autocomplete="off" /> <button>Send</button> </form> </div>
上述代码包含了一个用于显示时间的 div
元素,一个用于显示聊天消息的 ul
元素和一个输入框和按钮,用于发送聊天消息。
下面是用于与 SSE 服务器建立连接的 JavaScript 代码:
// javascriptcn.com 代码示例 const source = new EventSource('/sse'); source.onopen = function(event) { console.log('连接已开启!'); }; source.onmessage = function(event) { const data = JSON.parse(event.data); switch (data.event) { case 'welcome': console.log('欢迎消息:', data.data); break; case 'time': document.getElementById('time').innerHTML = `当前时间:${data.data}`; break; default: console.log('默认消息:', data.data); break; } }; source.onerror = function(event) { console.error('连接出错!'); };
上述代码通过 new EventSource('/sse')
建立了与服务器的 SSE 连接,并注册 onopen
、onmessage
和 onerror
三个事件, 最关键的是处理来自服务器的消息。当接收到消息时,客户端会根据消息类型,更新 UI 的不同组件。
最后,是处理用户发送聊天消息的 JavaScript 代码:
// javascriptcn.com 代码示例 const form = document.querySelector('form'); const input = document.querySelector('#message'); form.addEventListener('submit', (event) => { event.preventDefault(); const message = input.value; input.value = ''; // 发送聊天消息给 Socket.io 服务器 sseRouter.io.emit('message', message); }); sseRouter.io.on('message', (message) => { // 接收到广播的聊天消息后,添加到 UI 中 const messages = document.getElementById('messages'); const li = document.createElement('li'); li.innerText = message; messages.appendChild(li); });
上述代码通过获取 form
和 input
元素,监听表单提交事件,然后发送用户输入的聊天消息给 Socket.io 服务器;当收到服务器广播的聊天消息时,将其添加到 UI 中。
到此为止,前端部分的 SSE 实时聊天的最佳实践已经介绍完毕,完整的服务器和客户端代码请见示例代码。
总结
本文详细地介绍了利用 SSE 实现实时聊天的最佳实践,并附带示例代码和详细的指导意义。SSE 技术具有传输效率高、反应速度快、易于实现等优点,在实现实时通讯等场景中有着广泛的应用。希望通过本文,读者可以更好地理解 SSE 技术,并能够掌握 SSE 的基本原理和应用技巧。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65364a007d4982a6ebe4b835