Node.js中isValid函数始终返回undefined的解决求助
搞定你的isValid函数返回问题!
嘿,我来帮你捋清楚这个问题——你遇到的核心是异步操作的返回值陷阱,这在刚接触JavaScript异步编程的新手里特别常见,咱们一步步拆解:
为什么valid一直是undefined?
你写的con.query是个异步函数(数据库查询不会立刻完成,得等数据库返回结果),它的回调函数会在查询结束后才执行,但你的isValid函数在调用con.query之后就直接跑完了,根本没返回任何值!而回调里的return只是从回调函数本身返回,和外层的isValid半毛钱关系都没有——这就是为什么valid一直是undefined,而你加的console.log能正常执行(因为它在回调里,等查询完才跑)。
怎么解决?
有两种常用的方式,我都给你写清楚,你可以选适合自己的:
方法1:用回调函数(最基础的异步处理)
给isValid加个回调参数,等查询完成后把结果通过回调传出来:
// 调用的时候要传一个回调函数,拿到结果后再处理 isValid(houseNew, gameID, 1, function(err, result) { if (err) { console.error(err); return; } var valid = result; // 这里写拿到valid后要做的逻辑 }); function isValid(card, gameID, ph, callback) { var cardnumbers = 0; // 注意:改成参数化查询,避免SQL注入! con.query("SELECT * FROM games WHERE id = ?", [gameID], function (err, result) { if (err) { callback(err); // 把错误传给回调 return; } var cards = [ result[0].player1, result[0].player2, result[0].player3, result[0].player4, result[0].player5, result[0].house1, result[0].house2, result[0].house3, result[0].house4, result[0].house5 ]; for(var i = 0; i<10; i++) { if(cards[i] == card) { cardnumbers++; } } let returnValue; if(cardnumbers >= 4) { returnValue = 0; } else { if(ph == 0) { let lastCard, i=0; lastCard = cards[i]; i++; while(i<=4 && lastCard != 0) { lastCard = cards[i]; i++; } returnValue = lastCard == 0 ? i : 10; } else if (ph == 1) { let lastCard, i=0; lastCard = cards[i + 5]; i++; while(i<=4 && lastCard != 0) { lastCard = cards[i + 5]; i++; } returnValue = lastCard == 0 ? i : 10; } } callback(null, returnValue); // 把结果传给回调 }); }
方法2:用async/await(更现代的写法,像同步代码一样)
把数据库查询包装成Promise,然后用async/await来处理异步,代码看起来更清爽:
// 先把con.query包装成Promise函数 function query(sql, params) { return new Promise((resolve, reject) => { con.query(sql, params, (err, result) => { if (err) reject(err); else resolve(result); }); }); } // 把isValid改成async函数 async function isValid(card, gameID, ph) { var cardnumbers = 0; try { // 用await等待查询结果,就像同步代码一样 const result = await query("SELECT * FROM games WHERE id = ?", [gameID]); var cards = [ result[0].player1, result[0].player2, result[0].player3, result[0].player4, result[0].player5, result[0].house1, result[0].house2, result[0].house3, result[0].house4, result[0].house5 ]; for(var i = 0; i<10; i++) { if(cards[i] == card) { cardnumbers++; } } if(cardnumbers >= 4) { return 0; } else { if(ph == 0) { let lastCard, i=0; lastCard = cards[i]; i++; while(i<=4 && lastCard != 0) { lastCard = cards[i]; i++; } return lastCard == 0 ? i : 10; } else if (ph == 1) { let lastCard, i=0; lastCard = cards[i + 5]; i++; while(i<=4 && lastCard != 0) { lastCard = cards[i + 5]; i++; } return lastCard == 0 ? i : 10; } } } catch (err) { throw err; // 抛出错误,让调用方处理 } } // 调用的时候要注意:await只能在async函数里用,所以可以这样写 (async function() { try { var valid = await isValid(houseNew, gameID, 1); // 这里使用valid } catch (err) { console.error(err); } })(); // 或者用.then的方式(适合不能用await的场景) isValid(houseNew, gameID, 1) .then(valid => { // 这里使用valid }) .catch(err => { console.error(err); });
重要提醒:别踩SQL注入的坑!
你原来的SQL语句是直接把gameID拼进去的,这非常危险,容易被SQL注入攻击。我上面的代码都改成了参数化查询(用?占位,然后把参数放在数组里),这是后端开发的基本安全规范,一定要记住哦!
内容的提问来源于stack exchange,提问作者Andrei Serban
相关产品推荐
相关产品推荐

