Node.js中mssql模块跨文件连接的优化方案咨询
优化Node.js mssql连接复用方案
针对使用mssql包时连接以Promise形式返回、路由复用连接的痛点,以下两种方案可实现直接导入后调用query方法,无需重复处理连接,同时解决原有方案的弊端:
方案一:封装通用数据库操作方法
在数据库配置文件中封装好查询方法,路由直接调用即可,无需关注连接细节。
1. 数据库配置文件(db.js)
const sql = require('mssql'); const { normalizePort } = require('./handlers'); const { SQL_SERVER_USER, SQL_SERVER_PASSWORD, SQL_SERVER, SQL_SERVER_DATABASE, SQL_SERVER_PORT } = require('./configurations/appConfig'); const config = { user: SQL_SERVER_USER, password: SQL_SERVER_PASSWORD, database: SQL_SERVER_DATABASE, server: SQL_SERVER, port: normalizePort(SQL_SERVER_PORT), pool: { max: 10, min: 0, idleTimeoutMillis: 30000 }, options: { encrypt: true, trustServerCertificate: true, // 本地开发/自签名证书场景设置为true } }; // 初始化连接池Promise(仅执行一次) const poolPromise = sql.connect(config); // 封装通用查询方法 const query = async (sqlStatement, params) => { const pool = await poolPromise; try { return await pool.query(sqlStatement, params); } catch (err) { console.error('数据库查询异常:', err); throw err; // 抛出错误交由路由层处理 } }; // 封装模板字符串风格的参数化查询 const queryTemplate = async (strings, ...values) => { const pool = await poolPromise; try { return await pool.query(strings, values); } catch (err) { console.error('模板查询异常:', err); throw err; } }; module.exports = { query, queryTemplate };
2. 路由文件中使用
const express = require('express'); const router = express.Router(); const { query, queryTemplate } = require('../db.js'); router.get('/products', async (req, res) => { try { const result = await query('SELECT * FROM products'); res.setHeader("Content-Type", 'application/json; charset=utf-8'); res.status(200).send(JSON.stringify(result, null, 4)); } catch (err) { res.status(500).send('查询失败'); } }); router.post('/brands', async (req, res) => { try { // 使用模板字符串方式执行参数化查询 const result = await queryTemplate`SELECT * FROM brands`; res.setHeader("Content-Type", 'application/json; charset=utf-8'); res.status(200).send(JSON.stringify(result, null, 4)); } catch (err) { res.status(500).send('查询失败'); } }); module.exports = router;
方案二:使用Proxy代理连接Promise
通过Proxy代理自动处理连接的await逻辑,让调用方式更贴近直接操作连接池的体验。
1. 数据库配置文件(db.js)
const sql = require('mssql'); const { normalizePort } = require('./handlers'); const { SQL_SERVER_USER, SQL_SERVER_PASSWORD, SQL_SERVER, SQL_SERVER_DATABASE, SQL_SERVER_PORT } = require('./configurations/appConfig'); const config = { user: SQL_SERVER_USER, password: SQL_SERVER_PASSWORD, database: SQL_SERVER_DATABASE, server: SQL_SERVER, port: normalizePort(SQL_SERVER_PORT), pool: { max: 10, min: 0, idleTimeoutMillis: 30000 }, options: { encrypt: true, trustServerCertificate: true, } }; const poolPromise = sql.connect(config); // 创建Proxy,调用方法时自动等待连接池初始化 const db = new Proxy({}, { get(_, methodName) { return async (...args) => { const pool = await poolPromise; return pool[methodName](...args); }; } }); module.exports = db;
2. 路由文件中使用
const express = require('express'); const router = express.Router(); const db = require('../db.js'); router.get('/categories', async (req, res) => { try { // 直接调用db.query,无需手动await连接 const result = await db.query('SELECT * FROM categories'); res.setHeader("Content-Type", 'application/json; charset=utf-8'); res.status(200).send(JSON.stringify(result, null, 4)); } catch (err) { res.status(500).send('查询失败'); } }); module.exports = router;
方案优势
- 避免服务器启动阻塞:服务器无需等待数据库连接成功即可启动,静态资源和无数据库依赖的接口可正常访问,仅当首次执行数据库查询时才会等待连接初始化
- 消除冗余代码:路由中无需重复编写
const pool = await connection这类代码,直接调用查询方法即可 - 统一错误处理:数据库层可统一捕获连接或查询异常,路由层只需专注业务响应处理
内容的提问来源于stack exchange,提问作者Mahmoud Y3c
相关产品推荐
相关产品推荐

