Node.js+MSSQL并发请求出现UnhandledPromiseRejectionWarning问题求助
解决Node.js + node-mssql并发请求下的未处理Promise拒绝问题
嘿,这个问题我熟!你遇到的是并发请求共享数据库资源引发的竞态条件——单请求时资源不会冲突,但两个请求撞在一起时,复用的连接/请求对象被同时修改,就会抛出这类ReferenceError和未处理的Promise拒绝。
常见诱因
- 你在
sql.js里可能复用了同一个Request实例,没有给每个请求单独创建新的请求对象 - 没用到node-mssql自带的连接池,而是手动搞了个单连接让所有请求共享
- 异步操作里没加
try/catch捕获异常,导致Promise拒绝没被处理
一步步解决
1. 改用连接池管理数据库连接
node-mssql的连接池就是专门处理并发的,它会自动帮你管理连接的创建、复用和释放。修改你的sql.js:
// sql.js const sql = require('mssql'); // 配置你的数据库连接信息 const poolConfig = { user: '你的数据库用户名', password: '你的数据库密码', server: '数据库地址', database: '目标数据库', pool: { max: 10, // 最大同时连接数,按需调整 min: 0, idleTimeoutMillis: 30000 // 闲置连接30秒后释放 }, options: { encrypt: true, // 如果你用的是Azure SQL,必须开这个 trustServerCertificate: false } }; // 初始化全局连接池 const pool = new sql.ConnectionPool(poolConfig); const poolConnect = pool.connect(); // 提前建立连接池 // 封装通用查询函数,每个请求都用独立的Request async function runQuery(sqlStatement, params = []) { await poolConnect; // 确保连接池已经初始化完成 try { const request = pool.request(); // 每个请求新建一个Request实例,避免冲突 // 绑定参数(如果有的话) params.forEach((val, idx) => { request.input(`param${idx}`, val); }); const result = await request.query(sqlStatement); return result.recordset; } catch (err) { console.error('SQL执行出错:', err); throw err; // 把错误抛给上层controller处理 } } module.exports = { runQuery };
2. 在Controller里做好异常捕获
就算底层函数抛出错误,上层也要用try/catch接住,不然就会出现UnhandledPromiseRejection警告:
// controller.js const { runQuery } = require('./sql.js'); async function handleYourRequest(req, res) { try { const result = await runQuery('SELECT * FROM YourTable WHERE Id = @param0', [req.params.id]); res.status(200).json(result); } catch (err) { res.status(500).json({ error: '服务器出错', details: err.message }); } }
3. 绝对不要共享Request/Connection实例
划重点!永远不要让多个请求共用同一个Request或者Connection对象,每个请求都应该从连接池拿独立的资源,用完后连接池会自动回收,不会出现冲突。
验证一下
你可以用工具模拟并发请求测试,比如用Apache Bench:
ab -n 100 -c 10 http://localhost:3000/你的接口路径
如果修改后没有再出现那些错误,就说明问题解决啦!
内容的提问来源于stack exchange,提问作者AJ_
相关产品推荐
相关产品推荐

