Node.js自定义JS函数返回MySQL数据问题及异步改造报错
问题分析与解决方案
初始代码返回undefined的原因
JavaScript中数据库查询是异步操作,你的初始代码里getAllUrls函数在conn.query的回调执行前就已经执行完conn.end()并结束了函数,此时result还没被赋值,函数没有返回有效数据,所以调用时得到undefined。同时conn.end()提前执行还会导致查询未完成就断开连接。
改造后连接关闭错误的原因
在egallery.js模块加载阶段,你先调用conn.connect(),然后定义函数,紧接着直接执行conn.end()——这会导致数据库连接在模块加载完成后就被关闭。后续请求触发getAllUrls执行conn.query时,连接处于关闭状态,因此抛出Can't add new command when connection is in closed state错误。
推荐解决方案:使用数据库连接池(性能最优)
连接池可以复用数据库连接,避免频繁创建/销毁连接的性能损耗,是生产环境的首选方案。
1. 修改conn.js,创建连接池
const mysql = require('mysql2/promise'); // 替换为你的数据库配置 const pool = mysql.createPool({ host: '你的数据库主机地址', user: '数据库用户名', password: '数据库密码', database: '目标数据库名', connectionLimit: 10, // 连接池最大连接数 waitForConnections: true }); module.exports = pool;
2. 修改egallery.js,基于连接池封装查询函数
const pool = require('./conn.js'); async function getAllUrls() { try { // 使用连接池执行查询,直接返回结果 const [rows] = await pool.query('SELECT * FROM ray_url'); return rows; } catch (err) { // 抛出错误,让上层调用处理 throw err; } } module.exports = { getAllUrls };
3. 保留app.js的async/await调用,增加错误处理
let app = require('express')(); var egallery = require('./models/egallery.js'); app.set('view engine', 'ejs'); app.get('/e', async (req, res) => { try { const rows = await egallery.getAllUrls(); console.log(rows); res.render('pages/index', { rows: rows }); } catch (err) { // 捕获错误并返回友好提示 console.error(err); res.status(500).send('服务器内部错误'); } }) app.get('/e/about', function(req, res) { res.render('pages/about'); }); app.listen(3000, '0.0.0.0');
备选方案:每次查询临时创建连接(不推荐)
如果不想用连接池,可以在每次查询时创建连接,查询完成后再关闭:
// egallery.js修改为 const conn = require('./conn.js'); function getAllUrls() { return new Promise((resolve, reject) => { conn.connect((connectErr) => { if (connectErr) return reject(connectErr); conn.query('SELECT * FROM ray_url', (queryErr, result) => { // 查询完成后关闭连接 conn.end(); queryErr ? reject(queryErr) : resolve(result); }); }); }); } module.exports = { getAllUrls };
app.js的调用逻辑不变,同样需要保留错误处理。
内容的提问来源于stack exchange,提问作者hkguile
相关产品推荐
相关产品推荐

