Node.js中数据库查询函数返回undefined的问题排查
问题分析与解决方案
你遇到的问题核心是JavaScript的异步操作特性,getLedgerDetails里的connection.query是异步执行的,这就导致你直接返回结果的方式根本无法拿到数据,具体原因和解决办法如下:
为什么会输出undefined?
connection.query是一个异步数据库查询操作,它不会阻塞代码执行——当你调用getLedgerDetails时,函数会先执行到connection.query这一行,然后立刻结束并返回默认的undefined,而查询的回调函数要等数据库返回结果后才会执行。你在回调里写的return row[0],只是回调函数自身的返回值,根本不会传递到外层的getLedgerDetails函数中,所以getDetails里打印的自然是undefined。
另外,你代码里的JSON.stringify和JSON.parse是多余的,result本身就是数组对象,直接取result[0]即可,不需要额外转换。
解决方案1:使用回调函数传递结果
既然异步操作无法直接返回值,我们可以给getLedgerDetails添加一个回调参数,在查询完成后把结果通过回调传递出去:
var getLedgerDetails = function (name, id, res, callback) { var f = '%d %b %Y'; connection.query( "SELECT id,voucher_type,DATE_FORMAT(date,?) as date,amount,voucher_number FROM sales WHERE ledger_name=? and company_id=?", [f, name, id], function (err, result) { if (err) { console.log(err); callback(err, null); // 传递错误信息 } else { callback(null, result.length > 0 ? result[0] : null); } } ); }; getDetails = function(name, id, res){ getLedgerDetails(name, id, res, function(err, data) { if (err) { // 在这里处理错误 return; } console.log(data); // 这里就能拿到正确的第一条记录了 }); }
解决方案2:改用Promise + async/await(更推荐的现代写法)
回调嵌套多了容易陷入“回调地狱”,用Promise封装异步操作,再配合async/await可以让代码更像同步写法,可读性更强:
// 把getLedgerDetails封装成Promise var getLedgerDetails = function (name, id, res) { return new Promise((resolve, reject) => { var f = '%d %b %Y'; connection.query( "SELECT id,voucher_type,DATE_FORMAT(date,?) as date,amount,voucher_number FROM sales WHERE ledger_name=? and company_id=?", [f, name, id], function (err, result) { if (err) { console.log(err); reject(err); // 抛出错误 } else { resolve(result.length > 0 ? result[0] : null); } } ); }); }; // 用async/await调用异步函数 getDetails = async function(name, id, res){ try { const data = await getLedgerDetails(name, id, res); console.log(data); // 这里能拿到正确结果 } catch (err) { // 处理错误 console.error(err); } }
这种写法逻辑更清晰,也更容易维护复杂的异步流程。
内容的提问来源于stack exchange,提问作者primo
相关产品推荐
相关产品推荐

