为何checkUserNameIsUsed函数未返回布尔值却返回undefined?
问题排查:checkUserNameIsUsed函数返回undefined的原因
问题场景
Admin类中的checkUserNameIsUsed函数用于检查数据库中是否存在指定用户名,预期逻辑是:用户名已存在返回false,不存在返回true,但实际调用时该函数返回undefined,导致判断逻辑失效。
原函数代码:
class Admin { // This function checks if the username is already used. Error in return of function checkUserNameIsUsed(userName, tableName, proprtieName) { try { let sqlQuery = `select * from ${tableName} where ${proprtieName} = '${userName}'`; connectToMysql(); connection.connect((err) => { if (!err) { connection.query(sqlQuery, (err, result) => { if (!err) { if (result.length > 0) { console.log("this user name is used :", userName); return false; } else { return true; } } connection.end(); }) } else { console.log(err); connection.end(); return false; } }) } catch (error) { console.log(error); } } }
调用代码:
// Check if the user name is used if (admin.checkUserNameIsUsed(adminUserName,adminTable,adminUserNameInDB)===false){ res.status(400).send("The user name is used. Please choose another username"); return false; }
核心原因
1. 异步回调的返回值无法传递到外层函数
connection.connect()和connection.query()都是异步操作,它们的回调函数里的return语句,只能返回给回调函数自身,无法传递到外层的checkUserNameIsUsed函数。外层函数会在异步操作执行完毕前就已经执行结束,没有任何返回值,所以默认返回undefined。
2. 外层函数没有返回逻辑
整个checkUserNameIsUsed函数没有在任何同步代码块中返回值,也没有通过异步机制(比如Promise)把结果传递出去,导致函数执行完没有输出。
3. 错误处理不完整
connection.query()的错误分支没有返回逻辑,即使查询出错,也不会传递任何结果;- 外层的
try/catch只能捕获同步代码的错误,异步操作的错误无法被捕获到,进一步导致结果丢失。
修复方案
改用Promise封装异步逻辑,让函数能够正确返回异步操作的结果,同时优化SQL语句防止注入风险:
修复后的函数代码
class Admin { checkUserNameIsUsed(userName, tableName, proprtieName) { // 返回Promise对象,用于传递异步结果 return new Promise((resolve, reject) => { try { // 改用参数化查询避免SQL注入 const sqlQuery = `SELECT * FROM ${tableName} WHERE ${proprtieName} = ?`; connectToMysql(); connection.connect((err) => { if (err) { console.log("数据库连接失败:", err); connection.end(); resolve(false); // 连接失败时返回false return; } // 执行参数化查询 connection.query(sqlQuery, [userName], (err, result) => { connection.end(); // 无论成功失败都关闭连接 if (err) { console.log("查询出错:", err); resolve(false); return; } // 根据查询结果返回对应值 if (result.length > 0) { console.log("用户名已被占用:", userName); resolve(false); } else { resolve(true); } }); }); } catch (error) { console.log("同步代码出错:", error); resolve(false); } }); } }
修复后的调用代码
由于函数返回Promise,调用时需要用async/await或者.then()处理异步结果:
// 用async/await调用(需要在异步函数中执行) async function handleUsernameCheck() { const isUserNameAvailable = await admin.checkUserNameIsUsed(adminUserName, adminTable, adminUserNameInDB); if (!isUserNameAvailable) { res.status(400).send("用户名已被占用,请更换其他用户名"); return false; } // 后续业务逻辑 } // 或者用.then()链式调用 admin.checkUserNameIsUsed(adminUserName, adminTable, adminUserNameInDB) .then(isAvailable => { if (!isAvailable) { res.status(400).send("用户名已被占用,请更换其他用户名"); return false; } // 后续业务逻辑 });
内容的提问来源于stack exchange,提问作者Almashdaly
相关产品推荐
相关产品推荐

