在前端开发中,实时推送是一个常见的需求,比如在线考试中的成绩实时推送。Server-Sent Events (SSE) 是一种可以在客户端通过纯 JavaScript 代码监听服务器端实时消息的技术。在这篇文章中,我们将讨论如何使用 SSE 在在线考试成绩实时推送中实现实时通信。
SSE 简介
SSE 是一种 HTML5 规范中的服务器推送技术。与传统的长轮询或 WebSockets 相比,SSE 有如下一些优点:
- 使用原生的 HTTP 协议通信,无需任何插件或框架。
- 不需要建立 TCP 连接,减少网络延迟。
- 可以发送多个数据事件,每个事件都有自己的类型和数据。
简单实现
在实际项目中,我们常常使用 SSE 在服务器端向客户端推送数据。下面的示例代码演示了一个简单的实现方法,用于在线考试中实时推送成绩。
服务器端
我们在服务器端使用 Node.js 作为开发环境,使用 Express 框架托管页面和设置路由。在下面的例子中,我们向客户端推送一个随机生成的成绩数据,并设置事件名称为“score”。
// javascriptcn.com 代码示例 const express = require("express"); const app = express(); app.use(express.static(__dirname + "/public")); app.get("/score", function (req, res) { res.set({ "Cache-Control": "no-cache", "Content-Type": "text/event-stream", Connection: "keep-alive", }); setInterval(function () { let score = Math.floor(Math.random() * 101); res.write(`event: score\ndata: ${score}\n\n`); }, 1000); }); app.listen(3000, () => { console.log("Server ready on port 3000"); });
客户端
我们在客户端使用 JavaScript 代码监听从服务器端推送的数据事件,当事件名称为“score”时更新成绩。
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>SSE Demo</title> </head> <body> <h1>在线考试</h1> <h2>成绩:<span id="score">0</span></h2> <script> const source = new EventSource("/score"); const scoreEl = document.getElementById("score"); source.onmessage = function (event) { if (event.data !== "") { let data = JSON.parse(event.data); if (data.event === "score") { scoreEl.innerHTML = data.data; } } }; </script> </body> </html>
添加用户验证
在实践中,我们需要校验用户的身份并只向特定用户推送成绩数据。下面的示例代码演示了如何向特定用户推送数据。
服务器端
我们使用 Express 框架处理 HTTP 请求,并使用 cookie-parser 中间件读取 cookie 值。在下面的例子中,我们通过 cookie 中的用户 ID 来实现用户身份验证。此外,我们只向通过身份验证的用户推送数据。
// javascriptcn.com 代码示例 const express = require("express"); const cookieParser = require("cookie-parser"); const app = express(); app.use(express.static(__dirname + "/public")); app.use(cookieParser()); const userScores = {}; app.get("/score", function (req, res) { const userId = req.cookies.userId; if (userId && userId !== "" && userScores[userId] === undefined) { userScores[userId] = Math.floor(Math.random() * 101); } res.set({ "Cache-Control": "no-cache", "Content-Type": "text/event-stream", Connection: "keep-alive", }); const intervalId = setInterval(function () { if (!res.finished && userScores[userId] !== undefined) { res.write( `event: score\ndata: ${JSON.stringify({ score: userScores[userId], userId: userId, })}\n\n` ); } }, 1000); req.on("close", function () { clearInterval(intervalId); }); }); app.listen(3000, () => { console.log("Server ready on port 3000"); });
客户端
我们在客户端使用 JavaScript 代码发送 HTTP 请求并从服务器端接收数据事件。我们使用 fetch API 发送 HTTP 请求,并使用 SSE API 接收数据事件。
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>SSE Demo</title> </head> <body> <h1>在线考试</h1> <h2>成绩:<span id="score">-</span></h2> <script> const scoreEl = document.getElementById("score"); fetch("/score").then(function (response) { const source = new EventSource("/score"); source.onmessage = function (event) { if (event.data !== "") { let data = JSON.parse(event.data); if (data.score !== undefined && data.userId !== undefined) { if (data.userId === response.headers.get("user-id")) { scoreEl.innerHTML = data.score; } } } }; }); </script> </body> </html>
总结
SSE 技术使得我们可以通过简单的 HTTP 请求和实现推送服务向客户端提供实时通信。在在线考试等需要实时推送数据的应用中,SSE 可以大大提高用户体验。当然,在实践中,我们还需要考虑数据安全性和性能问题。在下一篇文章中,我们将讨论如何使用 WebSockets 技术实现实时通信。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654eaf4a7d4982a6eb7cba4d