Node.js Express 基于mssql跨库查询合并结果集同响应返回实现
原代码运行异常的核心原因
- 接口路由内的代码是同步执行逻辑,
res.send()会在两个SQL查询的异步回调还没触发、结果还没返回的时候就立刻执行,这时候两个结果集都还没被保存,返回的内容自然是空的 - 直接调用全局
mssql模块的connect、close方法,两个连续执行的数据库连接会共享同一个全局单例实例:第一次连接还在建立/查询执行的异步过程中,第二次connect就会覆盖全局的连接状态;等第一个查询执行完触发的sql.close(),会直接把刚建立的第二个连接强制关闭,导致第二个查询的回调还没拿到结果就被中断,最终出现第二个结果集始终为空的问题 - 所有数据库操作的错误仅打印在控制台,没有中断整个执行流程,接口会在出错的情况下依然返回空内容,没有明确的错误提示
代码调整方案
核心思路是:拆分独立的数据库连接资源,把异步查询过程用Promise封装,等两个查询全部执行完成后,再统一合并结果返回。
具体调整点:
- 针对每个独立的数据库配置,单独创建
ConnectionPool连接实例,不使用全局单例共享连接资源,从根源上避免两个连接互相被关闭、状态被覆盖的问题 - 把单库的查询逻辑封装为返回Promise的异步函数,替代原来的回调嵌套写法,方便并行等待两个查询的结果
- 路由内用
async/await等待两个查询的全部结果,确保res.send()不会提前执行 - 增加完整的错误捕获:只要任意一步连接、查询出现异常,就及时返回500状态和明确的错误信息,避免静默失败
- 所有数据库连接在查询完成/出错后自动释放,不要在全局层面提前调用
close方法中断执行流程
调整后的可运行参考代码
const express = require('express') const app = express() const cors = require('cors') const sql = require('mssql') app.use(cors()) const config_03 = { server: 'server01', // 原有数据库配置项保留 } const config_01 = { server: 'server01', // 原有数据库配置项保留 } /** * 执行单库查询的封装函数 * @param {object} dbConfig 对应数据库的连接配置 * @param {string} queryStr 要执行的SQL语句 * @returns {Promise<Array>} 查询返回的记录集 */ async function querySingleDb(dbConfig, queryStr) { // 每个查询使用独立的连接池,不与其他连接共享状态 const pool = await new sql.ConnectionPool(dbConfig).connect() try { const queryResult = await pool.request().query(queryStr) return queryResult.recordset } finally { // 无论查询成功或失败,用完即释放连接 pool.close() } } app.get('/api/', async (req, res) => { try { // 并行执行两个独立查询,等待全部结果返回 const [db03Result, db01Result] = await Promise.all([ querySingleDb(config_03, "select foo, bar from foobar"), querySingleDb(config_01, "select foo, bar from foobar") ]) // 合并两个结果集后统一返回 const mergedResponse = { dataFrom03: db03Result, dataFrom01: db01Result } res.send(mergedResponse) } catch (err) { // 任意环节出错则返回明确错误 res.status(500).send({ message: '数据库查询执行失败', errorDetail: err.message }) } }) const webserver = app.listen(5000, () => { console.log('node running') })
调整后的效果
- 从根源上解决第二个查询结果为空的问题:两个连接池完全独立,不会被全局的
close操作互相影响,查询流程不会被中途中断 - 不会再出现
res.send()提前执行的问题:接口会严格等待两个查询全部完成后,才把合并后的结果返回给请求方 - 两个查询并行执行,相比串行执行总响应耗时更短
- 完整的错误捕获机制,避免无提示的空返回问题,前端可以明确感知到查询执行异常
内容的提问来源于stack exchange,提问作者Ricardo Soares
相关产品推荐
相关产品推荐

