Node.js使用Promise查询mssql时如何返回全部结果行
问题说明
基于Promise封装mssql查询的GetProducts方法,开启流模式查询Products表时仅返回第一行数据,需要修改为返回全部查询结果。
原有错误实现
return new Promise((resolve, reject) => { sql.connect(config, err => { const request = new sql.Request() request.stream = true request.query('select * from Products') request.on('row', row => { const products = [{ id: row.ProductID, name: row.ProductName}] resolve(products) }) }) sql.on('error', err => { console.log(err) }) }) }
调用代码
GetProducts() .then((products) => { console.log(products) });
当前错误返回
[ { id: 1, name: 'Chai' } ]
错误原因
- Promise状态一旦变更就会凝固,原有代码在
row事件第一次触发(读到第一行数据)时就调用了resolve,后续读取到的行不会再触发返回 - 没有监听流读取完成的事件,无法获知所有行何时读取完毕
- 错误捕获逻辑不全,连接、查询阶段的错误没有正确透传给Promise的reject
修复方案
流模式修复(保留流读取逻辑)
提前初始化数组缓存每一行读取到的数据,等所有行读取完成触发done事件时,再调用resolve返回完整数组,同时补全全链路错误捕获:
function GetProducts() { return new Promise((resolve, reject) => { sql.connect(config, err => { if (err) return reject(err); const request = new sql.Request(); request.stream = true; const products = []; request.query('select * from Products'); // 逐行读取时仅做数据缓存,不执行resolve request.on('row', row => { products.push({ id: row.ProductID, name: row.ProductName }); }); // 所有行读取完成后返回完整结果 request.on('done', () => { resolve(products); }); // 捕获查询阶段错误 request.on('error', err => { reject(err); }); }); // 捕获数据库连接全局错误 sql.on('error', err => { reject(err); }); }); }
简化写法(无需流处理时推荐)
如果不需要逐行处理流数据,可以直接关闭流模式(mssql默认非流模式),查询回调会直接返回全量结果,代码更简洁:
function GetProducts() { return new Promise((resolve, reject) => { sql.connect(config, err => { if (err) return reject(err); const request = new sql.Request(); request.query('select * from Products', (err, result) => { if (err) return reject(err); const products = result.recordset.map(row => ({ id: row.ProductID, name: row.ProductName })); resolve(products); }); }); sql.on('error', reject); }); }
两种写法调用逻辑不变,执行后都会返回包含所有商品数据的数组。
内容的提问来源于stack exchange,提问作者aykutdede
相关产品推荐
相关产品推荐

