Socket IO客户端连接后无法推送SQL更新数据问题求助
问题排查与修复方案
核心问题点
- 代码仅在新客户端触发
connection连接事件时才会执行1次数据库查询,没有主动检测数据库变更的逻辑,自然数据库更新后不会主动推送给已在线的客户端 - 用单个变量
connectedSocketID存储连接ID,仅能支持1个客户端同时在线,新客户端连接会覆盖旧ID,多客户端场景无法正常使用 JSON.stringify比对对象的实现有隐式缺陷:对象键顺序不同、值为undefined/函数/存在循环引用时都会出现比对错误,可能漏掉真实的数据变更
修复代码
第一步:替换连接存储结构,新增定时轮询检测逻辑
const app = express(); const httpServer = require('http').createServer(app); const io = require('socket.io')(httpServer); const path = __dirname + '/views/'; let sqlQuery = require('./controllers/sqlController').queryDatabase; let currentQueryData = {}; // 替换为Set存储所有在线连接ID,支持多客户端 const connectedSockets = new Set(); app.use(express.static(path)) app.get('/', function (req,res) { res.sendFile(path + "index.html"); }); // 函数保留,用于给单个新连接发数据 const sendData = (data, socket) => { socket.emit('markerCreation', data); } // 替换为更严谨的深比对逻辑,避免JSON.stringify的坑 const compareObjects = (obj1, obj2) => { if (obj1 === obj2) return true; if (!obj1 || !obj2 || typeof obj1 !== 'object' || typeof obj2 !== 'object') return false; if (Array.isArray(obj1) && Array.isArray(obj2)) { if (obj1.length !== obj2.length) return false; return obj1.every((item, index) => compareObjects(item, obj2[index])); } const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2); if (keys1.length !== keys2.length) return false; return keys1.every(key => keys2.includes(key) && compareObjects(obj1[key], obj2[key])); } // 新增定时轮询任务,5秒查询一次数据库,间隔可根据实时性要求调整 setInterval(async () => { const newQueryData = await sqlQuery(); const dataChanged = !compareObjects(currentQueryData, newQueryData); if (dataChanged) { currentQueryData = newQueryData; // 数据变更后广播给所有已连接客户端 io.emit('markerCreation', currentQueryData); } }, 5000) httpServer.listen(3001, () => { console.log(`Server listening at ${3001}`); }) io.on('connection', async socket => { // 新连接加入在线集合 connectedSockets.add(socket.id); // 新连接直接返回当前最新数据 const newQueryData = await sqlQuery(); currentQueryData = newQueryData; sendData(currentQueryData, socket); // 连接断开时清理资源 socket.on('disconnect', () => { connectedSockets.delete(socket.id); }); });
可选优化(更高实时性+更低性能消耗)
如果对数据推送延迟要求很高,不想用轮询产生冗余查询,可以对接SQL Server的变更数据捕获(CDC) 功能,数据库数据有更新时主动触发推送逻辑,无需定时轮询。
内容的提问来源于stack exchange,提问作者jared abbott
相关产品推荐
相关产品推荐

