随着现代 web 技术的发展,客户端和服务器之间的实时通信变得越来越重要。传统上,web 应用程序通常使用轮询技术来定期向服务器发送请求以获取更新数据。这种方法通常会导致网络负载增加,并且不能实时更新数据。近年来,Server-Send Events (SSE) 成为了一种很好的解决方案,它可以实现在服务器端向客户端发送数据,实时通信、自动重连等特性使得它在 web 应用程序中得到广泛应用。
在本文中,我将向您介绍如何在 Node.js 中使用 SSE 进行实时通信,以及相关设计和技巧,您将会学会如何利用 SSE 的优势,在 web 应用程序中实现实时交互。
Server-Send Events(SSE)
Server-Send Events 是一种 HTML5 规范,用于实现服务器向客户端单向数据即时推送的功能。SSE 的核心优势在于服务器可以直接将数据发送给客户端,而不需要客户端发送请求来获取数据,这使得 SSE 成为实时通信的理想选择。
SSE 使用长轮询机制来实现数据传递,当客户端连接到服务器时,服务器会保持连接打开,直到有数据推送。当服务器有数据要推送时,它会将数据推送到客户端,并保持连接一段时间以确定客户端是否成功接收到数据。如果连接断开,则浏览器会尝试自动重连,直到连接成功或超出连接限制。
下面是一个简单的 SSE 实现例子:
// javascriptcn.com 代码示例 // server.js var http = require('http'); http.createServer(function(req, res) { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Access-Control-Allow-Origin': '*', 'Cache-Control': 'no-cache' }); setInterval(function() { res.write('data: ' + new Date().toLocaleTimeString() + '\n\n'); }, 1000); }).listen(3000, function() { console.log('server running on port 3000'); });
在浏览器中访问该页面,你会看到时间每秒钟更新一次。在服务端代码中,我们通过 http.createServer
来创建了一个 HTTP 服务器,然后我们为响应设置了 Content-Type
为 text/event-stream
,这是 SSE 的标准 MIME 类型。然后我们设置了允许跨域的 Access-Control-Allow-Origin
,并禁用了缓存 Cache-Control: no-cache
。
在我们的服务器中,我们开启了一个定时器,在每秒钟的间隔中,向客户端发送一个包含当前时间的数据块,数据块的格式如下:
data: {data}\n\n
其中,data
是我们要发送的数据。请注意,每个 SSE 数据块后面需要有两个换行符表示块结束。
在客户端代码中,我们可以通过创建一个事件源对象来接收 SSE 数据:
// client.js var eventSource = new EventSource('http://localhost:3000'); eventSource.addEventListener('message', function(e) { console.log(e.data); });
在上面的代码中,我们创建了一个名为 eventSource
的事件源对象,并将其连接到我们的 SSE 服务器。然后,当我们收到新的消息时,我们将其打印到控制台中。
集成 SSE 到前端应用
现在我们已经了解了 SSE 是什么,如何在服务端和客户端实现 SSE 流。接下来我们将使用 Node.js 和 SSE,来构建一个实时任务追踪应用程序。
1. 初始化项目
首先,我们需要初始化一个空的 Node.js 项目。我们可以通过运行以下命令来创建一个新的 Node.js 项目:
mkdir realtime-tasks-tracker cd realtime-tasks-tracker npm init -y
2. 安装依赖
接下来,我们需要安装一些依赖。我们将使用 Express.js 框架来搭建我们的 web 服务器,并使用 MongoDB 来存储任务数据。
npm install express mongodb cors
3. 创建服务器
接下来,我们将创建我们的 Express.js 服务器,并实现 SSE 服务器。我们将使用 MongoDB 存储我们的任务数据,并通过 SSE 将它们推送到客户端。
// javascriptcn.com 代码示例 // index.js const express = require('express'); const { MongoClient } = require('mongodb'); const cors = require('cors'); // Constants const MONGO_URL = 'mongodb://localhost:27017'; const DB_NAME = 'tasks-tracker'; const SSE_INTERVAL = 1000; // App const app = express(); app.use(cors()); // SSE app.get('/tasks-events', async (req, res) => { // Set headers for SSE res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '*' }); const client = await MongoClient.connect(MONGO_URL, { useNewUrlParser: true, useUnifiedTopology: true }); const db = client.db(DB_NAME); const tasks = db.collection('tasks'); // Send tasks data SSE events setInterval(async () => { const tasksData = await tasks.find().toArray(); const data = JSON.stringify(tasksData); const eventData = `data: ${data}\n\n`; res.write(eventData); }, SSE_INTERVAL); // Handle client closing the connection req.on('close', () => { client.close(); console.log('Client closed SSE connection'); }); }); // Start the server const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
在上面的代码中,我们启动了一个 Express.js 应用,并在 /tasks-events 路由中添加了 SSE 服务器。我们使用 MongoDB 存储任务数据,并在每秒钟的时间间隔中从数据集合中获取所有任务数据,并将其转换为 JSON 后,将其发送到客户端。
4. 创建客户端
最后,我们需要在客户端中订阅 SSE 数据并将其显示在页面上。
// javascriptcn.com 代码示例 <!-- index.html --> <!doctype html> <html> <head> <title>Realtime Tasks Tracker</title> </head> <body> <h1>Realtime Tasks Tracker</h1> <ul id="tasks-list"></ul> <script> // Subscribe to SSE events var eventSource = new EventSource('http://localhost:3000/tasks-events'); eventSource.addEventListener('message', function(e) { // Update tasks list with new data const tasks = JSON.parse(e.data); const tasksList = document.getElementById('tasks-list'); tasksList.innerHTML = ''; tasks.forEach(function(task) { const li = document.createElement('li'); li.innerText = task.title + ': ' + task.description; tasksList.appendChild(li); }); }); </script> </body> </html>
在上面的代码中,我们添加了一个订阅 SSE 事件的客户端 JavaScript 代码。在我们收到新的 SSE 消息时,我们使用接收到的 JSON 数据更新我们的任务列表。最终效果见下图:
总结
Server-Send Events(SSE)是一种实现服务器向客户端单向数据即时推送的功能,它的核心优势在于服务器可以直接将数据发送给客户端,而不需要客户端发送请求来获取数据,这使得 SSE 成为实时通信的理想选择之一。
在本文中,我们通过一个实时任务追踪应用程序使用 SSE 在 Node.js 中进行了实现。您已经了解了如何在服务器端和客户端实现 SSE 架构,如何使用 SSE 数据进行交互,以及如何使用 SSE 架构构建实时应用程序。我希望您现在能够独立地使用 SSE 架构并将其集成到您的自己的web应用程序中,使得它们可以实现实时通信和无缝更新。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65434e377d4982a6ebcfb977