调用searchAccessToken函数返回undefined问题(添加回调仍无效)
问题分析与解决方案
你遇到的核心问题是JavaScript异步操作的执行顺序,你的searchAccessToken函数里包含了异步的数据库操作(db连接和conn.query查询),但你试图用同步的方式返回结果,这就导致函数执行完毕时,异步操作还没完成,所以返回值是undefined。
先拆解下问题根源:
db(...)和conn.query(...)都是异步函数,它们的回调会在主线程空闲时才执行- 你原代码里的
return token是在异步回调内部执行的,并不是searchAccessToken函数本身的返回值,所以外部调用searchAccessToken(name)时,函数已经提前返回了默认的undefined
你尝试用回调修改的版本也存在问题:
db的回调函数签名是固定的(err, conn),你不能凭空添加callback参数,这个参数根本不会被传入- 你调用
searchAccessToken时也没有传入回调函数,即使写法正确,也无法获取结果
正确的回调写法
我们需要让searchAccessToken主动接受一个回调参数,在异步操作完成后调用这个回调来传递结果:
function searchAccessToken(emailAddress, callback) { // 重点:用参数化查询防止SQL注入,绝对不能直接拼接参数! var sql = "SELECT accessToken FROM device WHERE email_address = ?"; console.log(sql); db(function(err, conn) { if (err) { return callback(err); // 把错误传递给回调 } conn.query(sql, [emailAddress], function(err, results) { conn.release(); // 无论成功失败,都要释放数据库连接 if (err) { return callback(err); } var token = results.length ? results[0].accessToken : ""; callback(null, token); // 遵循Node.js回调规范:第一个参数是错误,第二个是结果 }); }); }
调用方式要改成传入回调函数:
searchAccessToken(name, function(err, userAccessToken) { if (err) { console.error("查询token失败:", err); return; } // 在这里使用userAccessToken,它会是预期的string类型 console.log("获取到的用户token:", userAccessToken); });
更优雅的Promise写法(推荐)
如果你的项目支持ES6+,可以把函数封装成Promise,避免回调嵌套的问题:
function searchAccessToken(emailAddress) { return new Promise((resolve, reject) => { var sql = "SELECT accessToken FROM device WHERE email_address = ?"; console.log(sql); db(function(err, conn) { if (err) { return reject(err); } conn.query(sql, [emailAddress], function(err, results) { conn.release(); if (err) { return reject(err); } var token = results.length ? results[0].accessToken : ""; resolve(token); }); }); }); }
调用时可以用async/await让代码更像同步逻辑:
async function getUserToken() { try { var userAccessToken = await searchAccessToken(name); console.log("获取到的用户token:", userAccessToken); // 在这里处理token } catch (err) { console.error("查询token失败:", err); } } getUserToken();
关键安全提醒
你原来的代码直接把emailAddress拼接到SQL语句中,这会导致严重的SQL注入漏洞!一定要用参数化查询(上面代码里的?占位符和[emailAddress]参数数组),让数据库驱动帮你处理参数转义,避免恶意攻击。
内容的提问来源于stack exchange,提问作者jdotdoe
相关产品推荐
相关产品推荐

