You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:33:30