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
相关产品推荐
相关产品推荐

