You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:05:35