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

Express JS 抽取SQL查询至独立文件后遇数据库超时问题求助

问题分析与修复方案

核心问题

你的代码超时根本原因是异步逻辑的时序错误:

  • doQuery是同步函数,但mysql的connect、query、end都是异步操作,函数会直接跳到最后一行返回504超时结果,完全没等异步回调执行。
  • 直接写在路由里能运行,是因为路由回调本身是异步上下文,异步操作的回调能正确触发响应;但抽成独立函数后,同步返回的永远是504,回调里的return对外层函数毫无意义。
  • connection.connect后显示disconnected,是因为你在同步代码里立刻查看状态,此时连接还没建立完成,而且你没等connect结束就直接执行query和end,导致连接还没就绪就被关闭,自然查不到数据也没错误日志(错误回调还没触发,函数就已经返回了)。

修复方案

方案1:用Promise封装异步逻辑

把doQuery改成返回Promise,路由用async/await等待结果:

修改SQL工具文件:

var mysql = require('mysql');

const connectionData = {
    host: 'localhost',
    user: 'root',
    password: '****',
    database: 'app'
};

module.exports = {
    doQuery: function (query) {
        return new Promise((resolve) => {
            const connection = mysql.createConnection(connectionData);
            
            connection.connect(error => {
                if (error) {
                    console.log(error);
                    resolve({
                        status: 502,
                        data: {error: {code: 502, message: "Database connection error."}}
                    });
                    connection.end();
                    return;
                }
                
                connection.query(query, (error, results) => {
                    // 先关闭连接再处理结果
                    connection.end(endError => {
                        if (endError) {
                            console.log(endError);
                            resolve({
                                status: 502,
                                data: {error: {code: 502, message: "Database connection error."}}
                            });
                            return;
                        }
                        
                        if (error) {
                            console.log(error);
                            resolve({
                                status: 500,
                                data: {error: {code: 500, message: "Internal server error"}}
                            });
                        } else if (results.length) {
                            resolve({
                                status: 200,
                                data: {data: results}
                            });
                        } else {
                            resolve({
                                status: 404,
                                data: {error: {code: 404, message: "Not Found"}}
                            });
                        }
                    });
                });
            });
        });
    }
}

修改路由代码:

router.get('/products', async function (req, res, next) {
    const response = await sqlHandler.doQuery('SELECT * FROM product');
    return res.status(response.status).json(response.data);
});

方案2:使用连接池(更推荐)

频繁创建销毁连接会损耗性能,用连接池可以复用连接,还能省去手动管理连接开闭的麻烦:

修改SQL工具文件:

var mysql = require('mysql');

const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: '****',
    database: 'app',
    connectionLimit: 10 // 根据业务调整连接数上限
});

module.exports = {
    doQuery: function (query) {
        return new Promise((resolve) => {
            pool.query(query, (error, results) => {
                if (error) {
                    console.log(error);
                    resolve({
                        status: 500,
                        data: {error: {code: 500, message: "Internal server error"}}
                    });
                    return;
                }
                
                if (results.length) {
                    resolve({
                        status: 200,
                        data: {data: results}
                    });
                } else {
                    resolve({
                        status: 404,
                        data: {error: {code: 404, message: "Not Found"}}
                    });
                }
            });
        });
    }
}

路由代码和方案1一致,用async/await调用即可。

关键提醒

  • 异步回调里的return无法返回给外层同步函数,必须用Promise、回调传参或者async/await来处理时序。
  • 永远要等待异步操作完成后再处理结果,不能跳过异步步骤直接返回。
  • 连接池是生产环境的最优选择,能有效提升数据库操作的性能和稳定性。

内容的提问来源于stack exchange,提问作者radek wilo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:15:29