NodeJS调用SQL Server存储过程出现Aborted错误的解决求助
问题背景
此前通过NodeJS API调用SQL Server存储过程获取电话类型数据正常,但调用获取军种分支的存储过程时,触发了来自PendingOperation.js的aborted错误,请求协助解决。
获取电话类型的代码
let query; query = env.STOREDPROCS.GET.PHONETYPES; // to add input var put @varname='' <-- VALUE let db = {}; module.exports = db; initializeDB(); async function initializeDB() { sql .connect(config) .then((dbConn) => { console.log("connected for phonetypes: ", query); dbConn.query(query, (err, data) => { if (err) { console.log("Error getting PhoneTypes from Stored Proc: ", err); sql.close(); } if (data) { console.log("ALL PHONE TYPES RETRIEVED: ", data); phonetypesDataArray.push(data.recordset); console.log("RECORDSET PHONETYPES: ", phonetypesDataArray); db.PhoneTypesModel = phonetypesDataArray; console.log("Phone Types Model: ", db.PhoneTypesModel); sql.close(); return db.PhoneTypesModel; } else { let errmsg = "NO RECORDS RETURNED for " + env.STOREDPROCS.GET.PHONETYPES; console.log(errmsg); phonetypesDataArray.push({ error: errmsg }); sql.close(); return phonetypesDataArray; } }); }) .catch((err) => { console.log("error", err); errmsg = `"Error Connecting to Database: ", ${err}`; phonetypesDataArray.push(errmsg); return phonetypesDataArray; }); }
获取军种分支的代码
let db = {}; module.exports = db; initializeDB(); async function initializeDB() { sql .connect(config) .then((dbConn) => { console.log("connected inside GET BRANCHES"); dbConn.query(query, (err, data) => { if (err) { console.log("Error getting BRANCHES OF SERVICE from Stored Proc: ", err); sql.close(); } if (data) { console.log("ALL BRANCHES OF SERVICE RETRIEVED: ", data); branchOfSvcDataArray.push(data.recordset); console.log("RECORDSET BRANCHES OF SERVICE: ", branchOfSvcDataArray); db.branchOfSvcDataArray = phonetypesDataArray; console.log("Branches of Service Model: ", db.branchOfSvcDataArray); sql.close(); return db.branchOfSvcDataArray; } else { let errmsg = "NO RECORDS RETURNED for " + env.STOREDPROCS.GET.BRANCHESOFSVC; console.log(errmsg); branchOfSvcDataArray.push({ error: errmsg }); sql.close(); return branchOfSvcDataArray; } }); }) .catch((err) => { console.log("error", err); errmsg = `"Error Connecting to Database: ", ${err}`; branchOfSvcDataArray.push(errmsg); return branchOfSvcDataArray; }); }
错误日志
[nodemon] restarting due to changes... [nodemon] starting `node index.js` [nodemon] restarting due to changes... [nodemon] starting `node index.js` Listening on port number: 8000 connected for phonetypes: usp_getPhoneTypes connected branches of service connected column info connected db-conn connected for getting column info: usp_getColumnInforForADB connected inside GET BRANCHES ALL PHONE TYPES RETRIEVED: { recordsets: [ [ [Object], [Object], [Object] ] ], recordset: [ { phone_types_id: 1, phone_type_name: 'CELL', rowCnt: 3 }, { phone_types_id: 2, phone_type_name: 'HOME', rowCnt: 3 }, { phone_types_id: 3, phone_type_name: 'WORK', rowCnt: 3 } ], output: {}, rowsAffected: [] } RECORDSET PHONETYPES: [ [ { phone_types_id: 1, phone_type_name: 'CELL', rowCnt: 3 }, { phone_types_id: 2, phone_type_name: 'HOME', rowCnt: 3 }, { phone_types_id: 3, phone_type_name: 'WORK', rowCnt: 3 } ] ] Phone Types Model: [ [ { phone_types_id: 1, phone_type_name: 'CELL', rowCnt: 3 }, { phone_types_id: 2, phone_type_name: 'HOME', rowCnt: 3 }, { phone_types_id: 3, phone_type_name: 'WORK', rowCnt: 3 } ] ]
Error getting BRANCHES OF SERVICE from stored procedure.
Error: abortedat PendingOperation.abort (C:\node-rest-api\node_modules\tarn\dist\PendingOperation.js:25:21)
at C:\node-rest-api\node_modules\tarn\dist\Pool.js:208:25
at Array.map ()
at C:\node-rest-api\node_modules\tarn\dist\Pool.js:207:53
at runNextTicks (node:internal/process/task_queues:61:5)
at processImmediate (node:internal/timers:437:9)NO RECORDS RETURNED for usp_getBranches
C:\node-rest-api\node_modules\tarn\dist\PendingOperation.js:25
this.reject(new Error('aborted'));Error: aborted
at PendingOperation.abort (C:\node-rest-api\node_modules\tarn\dist\PendingOperation.js:25:21)
at C:\node-rest-api\node_modules\tarn\dist\Pool.js:208:25
at Array.map ()
at C:\node-rest-api\node_modules\tarn\dist\Pool.js:207:53
at runNextTicks (node:internal/process/task_queues:61:5)
at processImmediate (node:internal/timers:437:9)[nodemon] app crashed - waiting for file changes before starting...
问题分析与解决方案
核心问题定位
- 未定义
query变量:军种分支代码中没有初始化query变量,直接调用dbConn.query(query)会触发错误,而电话类型代码中明确赋值了query = env.STOREDPROCS.GET.PHONETYPES。 - 连接池被过早关闭:两个模块都在请求完成后调用
sql.close(),这会关闭整个连接池,导致后续请求无法获取连接,触发tarn池的aborted错误(等待获取连接的操作被终止)。 - 变量混淆:军种分支代码中错误地将
phonetypesDataArray赋值给db.branchOfSvcDataArray,应该使用branchOfSvcDataArray。
修复步骤
1. 补全军种分支代码的query变量
在军种分支代码顶部添加:
let query; query = env.STOREDPROCS.GET.BRANCHESOFSVC;
2. 避免全局关闭连接池
不要使用sql.close(),而是释放单个连接。对于mssql库,dbConn是连接实例,请求完成后应调用dbConn.close()而非全局的sql.close()。全局sql.close()会销毁整个连接池,导致后续所有请求失败。
3. 修正变量赋值错误
将军种分支代码中的:
db.branchOfSvcDataArray = phonetypesDataArray;
改为:
db.branchOfSvcDataArray = branchOfSvcDataArray;
4. 改用async/await写法(推荐)
回调嵌套容易导致错误,改用async/await让代码更清晰,同时更好地处理异步流程:
let query = env.STOREDPROCS.GET.BRANCHESOFSVC; let db = {}; module.exports = db; (async function initializeDB() { try { const dbConn = await sql.connect(config); console.log("connected inside GET BRANCHES"); const data = await dbConn.query(query); console.log("ALL BRANCHES OF SERVICE RETRIEVED: ", data); branchOfSvcDataArray.push(data.recordset); console.log("RECORDSET BRANCHES OF SERVICE: ", branchOfSvcDataArray); db.branchOfSvcDataArray = branchOfSvcDataArray; console.log("Branches of Service Model: ", db.branchOfSvcDataArray); // 释放当前连接,而非关闭整个池 await dbConn.close(); return db.branchOfSvcDataArray; } catch (err) { console.log("Error getting BRANCHES OF SERVICE from Stored Proc: ", err); const errmsg = `Error Connecting to Database: ${err}`; branchOfSvcDataArray.push({ error: errmsg }); return branchOfSvcDataArray; } })();
额外建议
- 建立全局连接池:在应用启动时初始化一次连接池,而非每个模块单独创建连接,避免重复创建和关闭池的开销。
- 错误处理优化:确保在所有分支中都正确处理错误,避免未捕获异常导致应用崩溃。
- 变量声明检查:确保所有使用的变量都已正确声明和赋值,避免隐式全局变量。
内容的提问来源于stack exchange,提问作者Peter The Angular Dude

