Discord.js开发机器人集成Firebase实时数据库数据被重置问题求助
问题根本原因
- 异步逻辑错误:Firebase Realtime Database的
ref.on('value', callback)是持续监听方法,不返回Promise,你加的await完全不生效,代码会不等读取结果返回就直接执行后续的set操作,此时profileData和guildData还没被赋值,直接写入就会覆盖原有数据。 - Guild实例缺失兜底逻辑:读取Guild数据时没有判断空值,当Guild数据不存在时
guildData为null,直接写入会清空对应路径的所有数据。 - 监听器滥用:单次读取数据使用
on会创建持续触发的监听器,多次调用会造成内存泄漏,也可能导致回调重复执行覆盖数据。
修复方案
直接替换sendData.js的代码为以下版本:
const database = require('../firebase.js') const User = require('../data/user.js') const Guild = require('../data/guild.js') // 引入你定义的Guild类 module.exports = async (Discord, client, message) => { const guildID = message.guild.id; const userID = message.author.id; if (userID === client.user.id) return; // 用once替代on做单次读取,once返回Promise可正常await const userSnapshot = await database.ref(`/Users/${userID}-${guildID}`).once('value') let profileData = userSnapshot.val() ?? new User(userID, guildID) const guildSnapshot = await database.ref(`/Guilds/${guildID}`).once('value') let guildData = guildSnapshot.val() ?? new Guild(guildID) // 确认读取到数据后再写入,避免空值覆盖 await database.ref(`/Users/${userID}-${guildID}`).set(profileData) await database.ref(`/Guilds/${guildID}`).set(guildData) }
额外优化建议
- 如果你的业务逻辑中没有在本次调用中修改
profileData或guildData,可以直接删掉最后两个set操作,不需要每次读取都重新写入,浪费请求配额还会增加不必要的写入延迟。 - Node.js 12.16.1版本过旧,后续如果要升级discord.js v14+版本需要至少Node.js 16.9以上,有条件建议升级运行环境。
内容的提问来源于stack exchange,提问作者Antoine BASTIDE
相关产品推荐
相关产品推荐

