调用含数据库操作的initGame函数赋值时gameid始终为undefined如何解决
问题根因
- 你的
initGame函数中所有数据库操作都是异步回调模式,嵌套回调里的return game.insertId只会把值返回给dbCon.query的回调函数本身,不会作为initGame的返回值向外传递。 initGame函数本身没有写顶层的return语句,调用后默认返回undefined,这就是你拿到的gameid始终是undefined的原因。
修复方案
第一步:改造initGame为返回Promise的函数
把原来的嵌套回调包装在Promise中,成功时resolve返回gameid,出错时reject抛出错误:
function initGame (red, black, options) { return new Promise((resolve, reject) => { dbCon.connect(function(err) { if (err) return reject(err); dbCon.query("INSERT INTO options " +"VALUES (" +"0 ," + options.malusSize + ", " + options.sequenceSize +", " + options.throwOnWaste +", " + options.throwOnMalus +", " + "'"+options.variant+"'" +", " + options.turnsTimed +", " + options.timePerTurn +", " + options.roundsTimed +", " + options.timePerRound +", " + (options.roomName != "" ? "'"+options.roomName+"'" : "null" )+", " + (options.roomPassword != "" ? "'"+options.roomPassword+"'" : "null" )+");", function (err, option) { if (err) return reject(err); dbCon.query("INSERT INTO games " +"VALUES (" +"0 ," + option.insertId + ", " + "'"+red+"'" + ", " + "'"+black+"'" +");", function (err, game) { if (err) return reject(err); resolve(game.insertId); }); }); }); }) }
第二步:在异步函数中用await获取返回值
外部的startPendingRoom已经声明为async函数,直接添加await关键字调用initGame即可,建议补充try/catch捕获异常:
async function startPendingRoom (red, black) { try { var gameid = await initGame (red, black, returnPendingRoomIfExists (red).options); removePendingRoomIfExists (red); removePendingRoomIfExists (black); io.to (red).emit ('startOnlineGameRES', { gameid : gameid }); io.to (black).emit ('startOnlineGameRES' , { gameid : gameid }); console.log (red," vs. ", black, " gameid: ", gameid); updatePendingRoomsCLIENT (); } catch (err) { console.error('创建游戏失败:', err) io.to(red).emit('startOnlineGameRES', { error: '创建游戏失败' }) io.to(black).emit('startOnlineGameRES', { error: '创建游戏失败' }) } }
额外注意
当前代码直接拼接SQL字符串存在SQL注入风险,建议改用数据库驱动提供的参数化查询能力,不要直接把用户可控的参数拼接到SQL语句中。
内容的提问来源于stack exchange,提问作者user16644136
相关产品推荐
相关产品推荐

