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

Node.js生成的HTML页面无需重载即可与服务端通信的实现方案

实现方案

技术选型

使用Socket.IO实现双向通信,无需页面刷新,自带断线重连机制,开发成本远低于原生WebSocket,完全匹配你的需求。如果仅需要服务端单向推送结果,也可以用前端fetch发POST传ID配合SSE实现,开发成本略高。

依赖安装

先安装需要的依赖包:

npm install socket.io pg

服务端代码改造

const http = require('http');
const fs = require('fs');
const url = require('url');
const { Server } = require('socket.io');
// PostgreSQL连接配置,替换为你自己的数据库信息
const { Pool } = require('pg');
const pgPool = new Pool({
  user: '数据库用户名',
  host: 'localhost',
  database: '数据库名',
  password: '数据库密码',
  port: 5432,
});

const port = 3000;
let queryTimer = null;

const server = http.createServer(function (req, res) {
  // 根路径返回HTML页面
  if (req.url === '/' || req.url.startsWith('/?')) {
    const data = fs.readFileSync(__dirname + "/public/index.html");
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.write(data);
    res.end();
    return;
  }
  res.writeHead(404);
  res.end();
});

// 将Socket.IO挂载到http服务,共用服务端口
const io = new Server(server, {
  cors: { origin: "*" } // 本地开发使用,生产环境可替换为你的实际域名
});

// 处理WebSocket连接
io.on('connection', (socket) => {
  // 监听前端提交的ID
  socket.on('submitId', async (id) => {
    // 清理之前的定时任务,避免重复查询
    if (queryTimer) clearInterval(queryTimer);

    // 首次提交立即执行查询
    await queryAndSendResult(socket, id);

    // 每5秒执行一次查询,间隔可自行调整
    queryTimer = setInterval(async () => {
      await queryAndSendResult(socket, id);
    }, 5000);
  });

  // 客户端断开连接时清理定时器释放资源
  socket.on('disconnect', () => {
    if (queryTimer) clearInterval(queryTimer);
  });
});

// 封装SQL查询与结果推送逻辑
async function queryAndSendResult(socket, id) {
  try {
    // 使用参数化查询避免SQL注入,替换为你实际的查询语句
    const queryRes = await pgPool.query('SELECT * FROM 你的表名 WHERE id = $1', [id]);
    // 将查询结果推送给前端
    socket.emit('queryResult', queryRes.rows);
  } catch (err) {
    socket.emit('queryError', err.message);
  }
}

server.listen(port, () => {
  console.log(`服务运行在 http://localhost:${port}`);
});

前端页面改造

修改public/index.html代码:

<!DOCTYPE html>
<html>
<body>
<form id="id_form" method="get" autocomplete="on">
  <label for="id">BATMON ID: </label>
  <input type="text" id="id" name="id" autofocus><br>
  <input type="submit">
</form>
<!-- 用于展示查询结果的容器 -->
<div id="resultContainer"></div>

<!-- Socket.IO客户端由服务端自动托管,无需单独下载 -->
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
const form = document.getElementById('id_form');
const resultContainer = document.getElementById('resultContainer');

// 阻止表单默认提交的页面刷新行为
form.addEventListener('submit', (e) => {
  e.preventDefault();
  const id = document.getElementById('id').value.trim();
  if (id) {
    // 将ID发送给服务端
    socket.emit('submitId', id);
  }
});

// 监听服务端返回的查询结果,自行修改渲染逻辑
socket.on('queryResult', (data) => {
  resultContainer.innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
});

// 监听查询错误
socket.on('queryError', (err) => {
  resultContainer.innerHTML = `<p style="color:red">查询出错:${err}</p>`;
});
</script>
</body>
</html>

补充说明

你之前找不到POST传ID的方法,是因为表单默认提交会触发页面刷新,只要监听表单submit事件调用e.preventDefault()阻止默认行为,就可以用fetch任意发送GET/POST请求,无需页面重载。


内容的提问来源于stack exchange,提问作者Vijay Shastri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 05:24:03