背景
在前端开发中,我们经常会遇到实时消息传输的问题。特别是在聊天室或者实时数据监控等场景下,消息实时性是非常重要的。通常来说,我们可以通过 WebSocket 或者轮询等方式来实现消息传输。但如果是非即时聊天,实时性并不是特别重要,却需要减轻服务器压力,该怎么办呢?这时候 Server-Sent Events 就是一个不错的选择。
Server-Sent Events
Server-Sent Events 是一个 HTML5 的特性,它允许我们从服务器获取推送事件。相比 WebSocket,它更简单,并且可以通过 User-Agent 的缓存机制来降低服务器压力。
Server-Sent Events 的特点如下:
- 服务器可以不断发送数据给客户端,客户端可以实时接收。
- 支持断线重连。
- 支持 HTTP 缓存机制。
- 传输的数据格式为文本格式。
Server-Sent Events 的数据传输方式类似于 HTTP,但协议规范不同。客户端通过创建一个 EventSource 对象来连接服务器,然后通过监听 message 事件来实时接收数据。
实现
要使用 Server-Sent Events,我们需要做以下几个步骤:
1. 创建一个 EventSource 对象
var eventSource = new EventSource('/api/messages');
通过上述代码,我们创建了一个 EventSource 对象,并指定了服务器的消息推送接口。
2. 监听服务器发送的数据
eventSource.onmessage = function(event) { console.log(event.data); };
通过上述代码,我们可以在控制台打印出来服务器发送的数据。
3. 发送数据
res.write('data: ' + JSON.stringify({ name: 'Tom', message: 'Hello!' }) + '\n\n');
通过上述代码,我们可以在服务器端发送数据给客户端。
4. 关闭连接
eventSource.close();
通过上述代码,我们可以关闭 EventSource 连接。
案例
我们来看一个使用 Server-Sent Events 实现非即时聊天消息传输的案例。
客户端
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>聊天室</title> </head> <body> <ul id="messages"></ul> <form> <input id="name" placeholder="Name"> <input id="message" placeholder="Message"> <button>Send</button> </form> <script> var eventSource = new EventSource('/api/messages'); eventSource.onmessage = function(event) { var data = JSON.parse(event.data); var messages = document.getElementById('messages'); var item = document.createElement('li'); item.textContent = data.name + ': ' + data.message; messages.appendChild(item); }; document.forms[0].onsubmit = function() { var name = document.getElementById('name').value; var message = document.getElementById('message').value; var xhr = new XMLHttpRequest(); xhr.open('POST', '/api/messages'); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.send(JSON.stringify({ name: name, message: message })); return false; }; </script> </body> </html>
服务器端
const http = require('http'); const fs = require('fs'); http.createServer(function(req, res) { if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(fs.readFileSync(__dirname + '/index.html')); } else if (req.url === '/api/messages') { if (req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); setInterval(function() { res.write('data: ' + JSON.stringify({ name: 'Tom', message: 'Hello!' }) + '\n\n'); }, 5000); } else if (req.method === 'POST') { let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { res.end('ok'); console.log(body); }); } } }).listen(3000);
通过上述代码,我们创建了一个简单的聊天室,服务器每 5 秒向客户端发送一条消息,同时客户端可以通过页面向服务器发送消息,从而实现非即时聊天消息传输。
总结
通过本文,我们了解了如何使用 Server-Sent Events 解决非即时聊天消息的延迟问题。相比 WebSocket,Server-Sent Events 更简单,并且可以通过 User-Agent 的缓存机制来降低服务器压力,对处理大量非即时消息数据流的场景非常适用。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b05a55add4f0e0ff9b5c70