如何将Node.js接收的WebSocket实时数据流输出到浏览器DOM
实现方案
你的认知没错,Express作为服务端框架运行在Node环境,没有权限直接操作浏览器端的DOM。要实现服务端接收的WebSocket实时数据同步到前端页面,只需要在现有服务上新增一层WebSocket转发逻辑:Node端作为中间层,既对接第三方WebSocket服务拉取数据,也对前端提供WebSocket连接,收到第三方数据后实时推送给已连接的前端,前端收到数据后自行更新DOM即可。
步骤1:改造Node端代码
你原有Express代码漏了app初始化逻辑,同时需要在HTTP服务上挂载WebSocket服务,用于和前端通信,完整改造后代码如下:
const { log, error } = console; const express = require('express'); const path = require('path'); const WebSocket = require('ws'); // 初始化Express const app = express(); const PORT = 3000; // 启动HTTP服务 const server = app.listen(PORT, log(`server is running on ${PORT}`)); // 挂载WebSocket服务,和HTTP服务共用端口 const wss = new WebSocket.Server({ server }); // 存储所有连接到当前服务的前端客户端 const frontClients = new Set(); // 处理前端WebSocket连接 wss.on('connection', (clientWs) => { frontClients.add(clientWs); // 前端断开连接时从集合中移除 clientWs.on('close', () => { frontClients.delete(clientWs); }); }); // 原有第三方WebSocket连接逻辑 const remoteWsUrl = 'wss://websocket.example'; const remoteWs = new WebSocket(remoteWsUrl); remoteWs.on('message', (rawData) => { const wsMessages = JSON.parse(rawData); const wsMessagesTime = wsMessages.t; const wsMessagesData = wsMessages.d; console.log(wsMessagesTime, wsMessagesData); // 将收到的消息转发给所有已连接的前端 const sendData = JSON.stringify({ time: wsMessagesTime, data: wsMessagesData }); frontClients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(sendData); } }); }); // 原有静态资源配置 app.use(express.static('./public')); app.get('/', (req, res) => { console.log('root page logged'); res.sendFile(path.join(__dirname, './public/index.html')); });
注意:原有根路由
/没有返回响应,访问时会一直挂起,补上sendFile逻辑返回index.html即可。另外Node端的ws库使用事件监听写法,不要直接用浏览器环境的onmessage属性赋值方式。
步骤2:改造前端index.html代码
首先把带空格的DOM id改成合法格式(id中包含空格会导致getElementById等方法匹配异常),然后新增前端WebSocket连接和DOM更新逻辑,完整代码如下:
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>websocket testing</title> </head> <body> <h2>hi this is a test string</h2> <!-- 去掉id中的空格 --> <div id="websocket-data"></div> <script> // 连接本地Node服务的WebSocket const localWs = new WebSocket(`ws://${window.location.host}`); const container = document.getElementById('websocket-data'); localWs.onmessage = (event) => { const msg = JSON.parse(event.data); // 创建新的消息节点追加到容器中,不需要保留历史可以改成innerText直接覆盖 const msgItem = document.createElement('p'); msgItem.textContent = `[${new Date(msg.time).toLocaleString()}] ${msg.data}`; container.appendChild(msgItem); // 自动滚动到底部 window.scrollTo(0, document.body.scrollHeight); }; localWs.onerror = (err) => { console.error('WebSocket连接异常:', err); }; </script> </body> </html>
效果验证
重启Node服务后访问http://localhost:3000,Node端控制台打印WebSocket消息的同时,页面的websocket-data容器中会实时追加显示对应内容。如果不需要保留历史消息,把appendChild逻辑改成container.textContent = \[${new Date(msg.time).toLocaleString()}] ${msg.data}``即可实现内容实时覆盖。
内容的提问来源于stack exchange,提问作者an0nhi11
相关产品推荐
相关产品推荐

