如何将MySQL查询结果保存到JavaScript对象属性?解决异步问题
问题解决:异步查询导致Game对象属性未正确赋值
核心问题分析
你的代码存在两个关键问题:
- SQL查询逻辑错误:
WHERE id=id会被解析为查询所有id字段等于自身的记录,而非传入的参数id,根本查不到目标数据。 - 异步操作时序问题:
db.query是异步回调方法,调用firstGame.fetchGame(1)后会立即执行console.log,此时数据库查询还未完成,对象属性自然还是初始的null。
修复方案(基于Promise + async/await)
修改Game.js
const db = require('../mySqlConnection'); class Game{ constructor(){ this.id = null; this.player1 = null; this.player2 = null; } saveData(data) { // 数据库查询结果是数组,取第一条有效数据 const gameData = data[0]; this.id = gameData.id; this.player1 = gameData.player1; this.player2 = gameData.player2; } // 将fetchGame改为返回Promise的方法,便于异步控制 fetchGame(id){ return new Promise((resolve, reject) => { // 用占位符?传递参数,修正查询逻辑同时避免SQL注入 const q = "SELECT * FROM `games` WHERE `id` = ?"; db.query(q, [id], (err, data) => { if(err) { reject(err); return; } this.saveData(data); resolve(this); // 查询完成后返回当前实例 }) }) } } module.exports = Game
修改index.js
const Game = require('./components/game') // 用async函数包裹异步逻辑,等待查询完成后再打印结果 async function initGame() { var firstGame = new Game() await firstGame.fetchGame(1); console.log("index.js: " + JSON.stringify(firstGame)) } initGame();
更优实现方式
可以用静态工厂方法直接创建并初始化Game实例,省去先创建空对象再赋值的冗余步骤,代码更简洁健壮:
// Game.js优化版 const db = require('../mySqlConnection'); class Game{ constructor(gameData){ this.id = gameData.id; this.player1 = gameData.player1; this.player2 = gameData.player2; } // 静态工厂方法,直接返回初始化完成的Game实例 static async fetchGame(id){ return new Promise((resolve, reject) => { const q = "SELECT * FROM `games` WHERE `id` = ?"; db.query(q, [id], (err, data) => { if(err) { reject(err); return; } if(data.length === 0) { reject(new Error("未找到对应游戏记录")); return; } const game = new Game(data[0]); resolve(game); }) }) } } module.exports = Game
对应的index.js
const Game = require('./components/game') async function initGame() { try { const firstGame = await Game.fetchGame(1); console.log("index.js: " + JSON.stringify(firstGame)) } catch (err) { console.error(err); } } initGame();
额外注意事项
- 始终使用参数占位符
?传递SQL查询参数,避免SQL注入风险。 - 必须处理数据库查询的异常情况(比如找不到对应记录),避免程序意外崩溃。
内容的提问来源于stack exchange,提问作者Lukas Walter
相关产品推荐
相关产品推荐

