无需Express实现Server-Sent Events:在线时长统计网站搭建方法咨询
不用Express实现基于Server-Sent Events的在线时长统计网页
当然可以不用Express,直接用Node.js原生的http模块就能实现Server-Sent Events(SSE),进而完成在线时长统计功能。下面是具体实现步骤:
一、服务端代码(Node.js)
创建一个server.js文件,用原生http模块搭建SSE服务,同时维护用户的在线时长:
const http = require('http'); const url = require('url'); // 存储用户在线时长,key为用户标识,value为开始时间戳 const userOnlineRecords = new Map(); const server = http.createServer((req, res) => { const parsedUrl = url.parse(req.url); // 处理SSE请求 if (parsedUrl.pathname === '/sse') { // 设置SSE相关响应头 res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', // 允许跨域(如果客户端和服务端不在同一端口/域名) 'Access-Control-Allow-Origin': '*' }); // 生成唯一用户标识(这里用请求IP+随机数简单实现,生产环境可改用session或token) const userId = `${req.socket.remoteAddress}-${Math.random().toString(36).slice(2, 10)}`; // 记录用户上线时间 userOnlineRecords.set(userId, Date.now()); // 首次发送当前时长(初始为0) res.write(`data: {"userId": "${userId}", "onlineSeconds": 0}\n\n`); // 定时推送更新(每1秒发送一次) const intervalId = setInterval(() => { const startTime = userOnlineRecords.get(userId); const onlineSeconds = Math.floor((Date.now() - startTime) / 1000); // SSE消息格式:data: 内容\n\n res.write(`data: {"userId": "${userId}", "onlineSeconds": ${onlineSeconds}}\n\n`); }, 1000); // 监听客户端断开连接事件,清理记录和定时器 req.on('close', () => { clearInterval(intervalId); userOnlineRecords.delete(userId); console.log(`用户 ${userId} 已下线`); }); } // 处理静态页面请求 else if (parsedUrl.pathname === '/') { res.writeHead(200, {'Content-Type': 'text/html'}); // 直接返回客户端HTML内容,也可以读取本地文件,这里为了简化直接写在代码里 res.end(` <!DOCTYPE html> <html> <head> <title>在线时长统计</title> <style> body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; } .duration { font-size: 2em; color: #2c3e50; margin-top: 20px; } </style> </head> <body> <h1>当前在线时长</h1> <div class="duration">0 秒</div> <script> // 客户端SSE连接代码 const eventSource = new EventSource('http://localhost:3000/sse'); const durationEl = document.querySelector('.duration'); eventSource.onmessage = function(e) { const data = JSON.parse(e.data); durationEl.textContent = \`\${data.onlineSeconds} 秒\`; }; eventSource.onerror = function(e) { console.error('SSE连接出错:', e); eventSource.close(); }; </script> </body> </html> `); } // 404处理 else { res.writeHead(404); res.end('Not Found'); } }); const PORT = 3000; server.listen(PORT, () => { console.log(`服务运行在 http://localhost:${PORT}`); });
二、代码说明
服务端核心逻辑
- SSE响应头设置:必须指定
Content-Type: text/event-stream,同时禁用缓存、保持长连接。 - 用户标识与时长记录:用
Map存储每个用户的上线时间戳,客户端断开时清理记录。 - 定时推送:通过
setInterval每秒计算一次在线时长,以SSE格式推送给客户端。 - 静态页面返回:直接在服务端返回客户端HTML,避免额外的文件读取操作(简单场景下可用)。
客户端核心逻辑
- EventSource连接:创建
EventSource实例连接服务端的SSE接口。 - 接收消息更新UI:监听
onmessage事件,解析服务端发送的JSON数据,更新页面上的时长显示。 - 错误处理:监听
onerror事件,连接出错时关闭SSE连接。
三、运行步骤
- 确保已安装Node.js环境。
- 将上述代码保存为
server.js。 - 在终端执行
node server.js启动服务。 - 打开浏览器访问
http://localhost:3000,即可看到实时更新的在线时长。
四、注意事项
- 跨域问题:如果客户端和服务端不在同一域名/端口,服务端需要设置
Access-Control-Allow-Origin头,示例中已添加。 - 用户标识优化:示例中的用户标识是简单的IP+随机数,生产环境建议使用更可靠的方式(如用户登录后的token、session ID)。
- 资源清理:客户端断开连接时,服务端必须清理对应的定时器和用户记录,避免内存泄漏。
内容的提问来源于stack exchange,提问作者helloILearnProgramming
相关产品推荐
相关产品推荐

