如何使用Express、MySQL2与TS将数据库查询结果传递至控制器?
问题:MySQL查询返回包含
_rows/_fields的非预期对象,无法获取目标格式数据集 我的代码
控制器 blog.controller.ts
export const getAllBlogs = async(req: Request, res:Response) => { try { return findAllBlogs() } catch(err) { res.status(500) } }
服务 blog.service.ts
export const findAllBlogs = async() => { dotenv.config() const db = await mysql.createConnection({ user: process.env.USER, host: process.env.HOST, password: process.env.PASSWORD, database: process.env.DB, }) let result = await db.execute('SELECT * FROM blogs', (err, result) =>{ if (err) { console.log(err) } if(Array.isArray(result) && result.length != 0) { return result } else { return err } }) return result }
期望结果
[ { "id": 1, "body": "This is a body", "title": "This is a title" } ]
package.json 配置
"devDependencies": { "@types/express": "^4.17.17", "@types/mysql": "^2.15.21", "@types/node": "^20.6.2", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "concurrently": "^8.2.1", "eslint": "^8.49.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.28.1", "eslint-plugin-n": "^16.1.0", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-promise": "^6.1.1", "express": "^4.18.2", "nodemon": "^3.0.1", "prettier": "^3.0.3", "prettier-eslint": "^15.0.1", "typescript": "~5.1.3" }, "dependencies": { "body-parser": "^1.20.2", "dayjs": "^1.11.9", "dotenv": "^16.3.1", "express-async-handler": "^1.2.0", "mysql2": "^3.6.1" }
问题原因及修复方案
1. db.execute混用回调与await导致结果异常
mysql2中,如果给execute传回调函数,await拿到的是原始查询结果对象(包含_rows、_fields),而非回调里的返回值——回调的return对外部变量完全无效,因为回调是异步执行的。
2. 数据库连接滥用
每次调用findAllBlogs都创建新连接,不仅浪费资源,还可能因连接未关闭导致异常。应该用连接池复用连接。
3. 控制器未发送响应
getAllBlogs只是return了查询结果,但没有通过res.send()把数据返回给客户端,前端自然拿不到内容。
4. dotenv.config()调用位置错误
应该在项目入口文件(比如app.ts/index.ts)里只调用一次,无需在每个服务函数里重复执行。
修正后的代码
1. 项目入口(比如app.ts)
先加载环境变量:
import dotenv from 'dotenv'; dotenv.config(); // 只在这里调用一次 // 其他初始化代码(express、路由等)
2. 服务 blog.service.ts
改用连接池,去掉回调,直接解构execute的返回值:
import mysql from 'mysql2/promise'; // 导入promise版本 // 创建连接池(全局只初始化一次) const pool = mysql.createPool({ user: process.env.USER, host: process.env.HOST, password: process.env.PASSWORD, database: process.env.DB, waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); export const findAllBlogs = async() => { try { // execute返回 [rows, fields],解构拿到行数据 const [rows] = await pool.execute('SELECT * FROM blogs'); return rows; } catch (err) { console.error('查询出错:', err); throw err; // 抛出错误让控制器处理 } }
3. 控制器 blog.controller.ts
添加响应发送逻辑:
export const getAllBlogs = async(req: Request, res:Response) => { try { const blogs = await findAllBlogs(); res.status(200).json(blogs); // 返回JSON格式的博客数据 } catch(err) { console.error('获取博客失败:', err); res.status(500).json({ message: '服务器内部错误' }); // 错误时返回提示 } }
这样修改后,findAllBlogs就能返回你期望的数组格式数据,控制器也能正确把数据发送给客户端。
内容的提问来源于stack exchange,提问作者Tevop
相关产品推荐
相关产品推荐

