使用tedious查询Azure SQL数据库返回用户的已填充数组为空如何解决
问题触发原因
- 核心为异步执行时序不匹配:tedious的数据库查询是事件驱动的异步操作,
connection.execSql(request)执行后不会阻塞后续代码运行,代码会直接执行res.send(result)。此时row事件还未触发,查询结果还没写入result数组,因此接口返回空数组。你本地调试时能看到result有值,是因为你查看变量的时机晚于查询完成时间,和接口响应的触发时序不一致。 - 额外潜在问题:原代码中
result未做变量声明属于隐式全局变量,并发请求时会出现不同请求的结果互相污染的问题。
解决方案
核心逻辑是将返回响应的操作放到查询完全结束的回调中,确保所有行数据都已经处理完成后再返回结果,修正后的代码如下:
router.get('/', async (req, res) => { // 声明为局部变量,避免全局污染 const result = [] const request = new Request( `SELECT TOP (5) [LogID] ,[OpdrachtID] ,[ChangeLog] ,[TimeStamp] ,[PersonID] FROM [log].[LOpdracht]`, function (err, rowCount, rows) { if (err) { // 错误捕获,返回合理的错误响应 return res.status(500).json({ error: err.message }) } // 查询全部完成后再返回结果,res.json会自动序列化数组为JSON格式 res.json(result) }) request.on('row', function(columns){ const rowData = {} columns.forEach(function(column){ rowData[column.metadata.colName] = column.value }) result.push(rowData) }) connection.execSql(request) })
本次修改的核心调整点:
- 把
res.send移到Request实例的回调函数内,该回调会在所有行处理完成、查询结束后触发,此时result已经完整填充了所有查询结果 - 给
result、rowData添加了局部变量声明,避免并发请求时数据串扰 - 新增了错误处理逻辑,查询出错时主动返回500错误,避免请求挂起
- 用
res.json替代res.send,明确返回JSON格式,符合需求
内容的提问来源于stack exchange,提问作者Bjop
相关产品推荐
相关产品推荐

