Node.js项目集成MySQL写入游戏得分数据不生效问题
问题根因
- 核心错误是运行环境混淆:你把只能在Node.js服务端运行的数据库操作代码,直接写到了前端页面的
<script>标签中。浏览器环境既不支持CommonJS规范的require()语法,也无法直接加载mysql这个Node.js专属npm包,这段代码在浏览器加载时就会直接抛出语法/运行时错误,根本不会执行到数据库写入逻辑。 - 你单独跑通的测试代码是直接在Node.js运行时执行的,和用户浏览器里运行的前端代码属于完全隔离的两个运行环境,环境差异是数据写不进去的核心原因。
- 附带逻辑缺陷:就算忽略环境问题,你原有写法在调用
connection.query()发起异步查询后,立刻执行connection.end()关闭连接,查询请求还没来得及发送到MySQL就被断开,同样会导致写入失败;另外直接拼接SQL字符串存在SQL注入风险,页面里的表格闭合标签误写为</tabl>也会造成DOM渲染异常。
修复方案
整体遵循「前端只做交互和请求、服务端处理数据库操作」的前后端分层逻辑,不要在前端写任何数据库相关代码:
- 第一步:在Node.js服务端新增得分上报接口
找到你启动本地Web服务的Node.js入口文件,新增HTTP接口处理得分写入、榜单查询逻辑,推荐使用MySQL连接池复用连接,避免频繁建连销毁的性能损耗,参考代码:
// 以下代码写在Node.js服务端文件中,不要写入前端HTML const express = require('express') // 若使用其他Web框架,逻辑保持一致即可 const mysql = require('mysql') const app = express() // 解析POST请求的JSON格式参数 app.use(express.json()) // 初始化MySQL连接池 const dbPool = mysql.createPool({ host: 'localhost', user: 'root', password: '441441', database: 'app', connectionLimit: 10 // 保留10个连接复用 }) // 得分上报接口 app.post('/api/report-score', (req, res) => { const { userName, score } = req.body // 基础参数校验 if (!userName || typeof score !== 'number') { return res.status(400).json({ code: 1, msg: '参数非法' }) } // 用参数化查询执行写入,避免SQL注入 const insertSql = 'INSERT INTO top5(Name, Score) VALUES (?, ?)' dbPool.query(insertSql, [userName, score], (insertErr) => { if (insertErr) { console.error('得分写入失败:', insertErr) return res.status(500).json({ code: 1, msg: '写入失败' }) } // 写入成功后查询Top5榜单返回给前端 const rankSql = 'SELECT Name AS userName, Score AS score FROM top5 ORDER BY Score DESC LIMIT 5' dbPool.query(rankSql, (rankErr, rankList) => { if (rankErr) { console.error('榜单查询失败:', rankErr) return res.status(500).json({ code: 1, msg: '榜单查询失败' }) } res.json({ code: 0, data: rankList }) }) }) }) // 保留你原有的静态页面托管逻辑,比如托管HTML、JS、CSS静态资源 // app.use(express.static('./public')) // 启动服务,端口和你原有配置保持一致即可 app.listen(3000, () => { console.log('服务已启动') })
- 第二步:修改前端弹球命中逻辑
把前端<script>里所有require('mysql')、创建数据库连接、执行SQL的代码全部删除,命中槽位计算出对应分值后,通过HTTP请求调用刚才写的服务端接口即可,参考修改:
// 以下代码运行在浏览器端,不要出现任何数据库账号、连接相关逻辑 function getBucket(chip) { let total = 0 $.each(chip.path, function(i, e) { total += e }) let score = 0 switch(total) { case -4: case 4: score = 50 break case -2: case 2: score = 1 break case 0: score = 10 break default: $(chip.el).remove() return } // 上报得分到服务端 fetch('/api/report-score', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userName: data.describe, // 对应当前得分的用户名称 score: score }) }) .then(res => res.json()) .then(res => { if (res.code === 0) { // 写入成功,用返回的Top5数据更新页面榜单 renderRankBoard(res.data) // 自行实现榜单渲染逻辑,把数据插入到页面对应位置 } }) .catch(err => console.error('得分上报失败:', err)) $(chip.el).remove() }
- 额外修复点:把你页面里写错的表格闭合标签
</tabl>改成</table>,避免DOM渲染异常。
安全提示:绝对不要在前端代码里写数据库连接地址、账号、密码,所有数据库操作必须收口到服务端,否则任何人打开浏览器控制台就能拿到你的数据库权限,随意删改数据。
内容的提问来源于stack exchange,提问作者Arunas
相关产品推荐
相关产品推荐

