Node.js类中方法返回undefined及this._data丢失问题求助
问题分析与解决方案
咱们来一步步拆解你遇到的两个核心问题:
1. getQuests 方法返回 undefined 的原因
connection.query 是异步操作——它不会阻塞代码执行,当你调用 getQuests() 时,函数会立刻执行到 connection.query() 这一行,然后直接结束(没有返回任何值,所以默认返回 undefined)。而你写在回调函数里的 return structure,只是回调自身的返回值,根本不会被外部的调用者获取到。
简单说:你的 return 语句在异步回调里,等它执行的时候,getQuests 早就已经执行完了。
2. this._data 数据丢失的问题
在JavaScript的普通函数回调中(比如你传给 connection.query 的匿名函数),this 的上下文会发生变化——它不再指向你的类实例,而是指向调用这个回调的对象(这里是和connection相关的上下文)。虽然你的代码里在回调外部提前取了 id 和 lvl,暂时没影响,但如果后续在回调里需要访问 this._data,就会拿到错误的值;另外如果异步过程中类实例被意外修改,也可能导致数据丢失,但核心问题还是回调的this指向偏差。
修复方案
我们可以用Promise + async/await来处理异步逻辑,同时用箭头函数或提前保存上下文来解决this指向问题:
重构后的代码示例
method.getQuests = async function() { // 提前保存当前类实例的上下文,避免回调中this指向混乱 const self = this; const id = self._data[0].id; const lvl = self._data[0].level; const structure = []; // 将异步的query操作包装成Promise,方便用await等待结果 const rows = await new Promise((resolve, reject) => { connection.query("SELECT * FROM quest WHERE player_id = ?", [id], function(errors, rowss) { if (errors) { reject(errors); return; } resolve(rowss); }); }); // 处理查询到的结果 for(let i = 0; i < rows.length; i++){ const rewards = { "coins": rows[i].gold, "xp": rows[i].experience, "honor": rows[i].honor, "premium": rows[i].donut, "statPoints": 0, "item": 0 }; structure.push({ "id": rows[i].id, "character_id": id, "identifier": rows[i].name, "type": 1, "stage": rows[i].stage, "level": lvl, "status": 1, "duration_type": 1, "duration_raw": (rows[i].duration * 60) * 4, "duration": rows[i].duration * 60, "ts_complete": 0, "energy_cost": rows[i].duration, "fight_difficulty": 0, "fight_npc_identifier": "", "fight_battle_id": 0, "used_resources": 0, "rewards": JSON.stringify(rewards) }); } return structure; };
关键修改点:
- 用
async标记方法,将异步查询包装成Promise并通过await等待完成,这样return structure就能正确返回结果 - 提前保存
self = this确保上下文正确,你也可以把query的回调换成箭头函数(箭头函数会自动继承外部的this) - 增加了错误处理逻辑,将查询错误通过
reject抛出,方便调用方捕获并处理
调用方式
因为方法现在是async函数,调用时需要用await或者.then():
// 在async函数内部调用 const quests = await yourClassInstance.getQuests(); // 或者用.then()链式调用 yourClassInstance.getQuests().then(quests => { console.log(quests); }).catch(err => { console.error('查询任务列表出错:', err); });
内容的提问来源于stack exchange,提问作者Eptun
相关产品推荐
相关产品推荐

