Docker部署后NodeJS中MySQL查询返回空对象问题排查
问题原因及解决方法
核心问题分析
1. 异步函数未正确处理
getAll是异步函数,调用时未用await或.then()处理Promise,导致路由直接返回Promise对象给客户端,Express会将其序列化为空对象。同时try/catch无法捕获异步函数的错误,因为错误被包裹在Promise中。
2. 查询方法Promise化错误
connection.query.bind(connection)仅绑定了this上下文,返回的仍是基于回调的函数,并非Promise。直接await该函数不会等待查询完成,rows无法获取正确的查询结果。
3. 结果处理逻辑缺陷
result未初始化,若查询结果为空或遍历逻辑错误,最终返回undefined,Express会将undefined转为空对象响应。- 遍历
Object.keys(rows)并覆盖result的逻辑错误:mysql模块查询结果默认是数组,遍历索引后result只会保留最后一条数据,而非全部结果。
4. 连接未释放(隐藏隐患)
查询完成后未释放连接回池,长期运行会导致连接池耗尽,引发新问题。
修复步骤
修复路由函数
将路由改为异步函数,使用await等待查询结果,并正确捕获错误:
router.get('/product-page', async (req, res) => { try { const data = await getAll(req); res.send(data); } catch (error) { logger.customLogger.log('debug', 'route error', error); res.status(500).send({ error: '查询失败' }); } });
修复查询函数
正确Promise化查询方法,简化结果处理,并释放连接:
async function getAll(req) { const connection = await util.promisify(pool.getConnection.bind(pool))(); console.log(`connected as id ${connection.threadId}`); logger.customLogger.log('debug', 'await-connection', 'connection'); // 正确包装查询方法为Promise const query = util.promisify(connection.query).bind(connection); const rows = await query('SELECT * FROM cam_features'); logger.customLogger.log('debug', 'result:', rows); // 直接返回查询结果(mysql默认返回数组,包含所有行) const result = rows; // 释放连接回池 connection.release(); return result; }
Docker环境额外检查
- 确认Docker Compose中数据库服务名称为
sql,应用容器与数据库容器处于同一网络,能正常解析该主机名。 - 验证
paragon数据库中cam_features表存在且有数据,避免初始化脚本未正确执行。 - 确认数据库用户
root拥有paragon数据库的查询权限。
内容的提问来源于stack exchange,提问作者Yenmangu
相关产品推荐
相关产品推荐

