使用Express.js与SQL Server时res.send返回空字典的问题
问题分析与解决方案
核心错误点
await未生效,异步执行顺序混乱:你的queryDatabase是基于回调的函数,没有返回Promise对象,await无法等待查询完成。循环会直接走完所有queryDatabase调用(但查询仍在后台异步执行),随后立刻执行res.send,此时response还未被赋值,自然是空的。- 重复创建数据库连接:每次循环都调用
sql.connect,会重复建立数据库连接,既降低效率,还可能引发连接泄漏问题。 - 未声明的全局变量:
tableNames没有用let/const声明,会成为全局变量,容易引发意外的变量污染问题。
修正方案
第一步:将queryDatabase改为Promise风格
推荐使用连接池复用连接,避免重复建立连接:
// 提前创建数据库连接池 const pool = new sql.ConnectionPool(dbConfig); const poolConnect = pool.connect(); // 封装Promise风格的查询函数 function queryDatabase(query) { return poolConnect.then(() => { const request = new sql.Request(pool); return request.query(query); }); }
第二步:修改路由处理逻辑
方式一:串行查询(按顺序依次查询表)
app.post('/api/v1/test', async (req, res) => { const tableNames = ["test", "test2"]; const response = {}; try { for (const table of tableNames) { const query = `SELECT * FROM ${table}`; const result = await queryDatabase(query); response[table] = result.recordset; } res.send({ statusCode: 200, data: response }); } catch (err) { console.error(err); res.status(500).send({ statusCode: 500, error: err.message }); } });
方式二:并行查询(同时发起所有表查询,效率更高)
app.post('/api/v1/test', async (req, res) => { const tableNames = ["test", "test2"]; try { // 并行发起所有查询请求 const queryPromises = tableNames.map(async table => { const query = `SELECT * FROM ${table}`; const result = await queryDatabase(query); return { [table]: result.recordset }; }); // 等待所有查询完成,合并结果到字典 const results = await Promise.all(queryPromises); const response = Object.assign({}, ...results); res.send({ statusCode: 200, data: response }); } catch (err) { console.error(err); res.status(500).send({ statusCode: 500, error: err.message }); } });
内容的提问来源于stack exchange,提问作者Stoobish
相关产品推荐
相关产品推荐

