使用discord.js+MongoDB开发Discord等级系统时遇‘level is not a constructor’错误
问题修复:"level is not a constructor" 错误
错误核心原因
你在创建新等级文档时,误用了回调函数里的level变量(它是findOne返回的查询结果,不是Mongoose模型构造函数),正确的做法是使用你导入的Level模型来实例化新文档。
修复后的完整代码
const { Events, Message } = require("discord.js"); const Level = require("../models/Level"); const getLevelXP = require("../utility/getLevelXP"); function getRandomXP(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; } module.exports = { name: Events.MessageCreate, async execute(message) { if (!message.inGuild() || message.author.bot) return; const XPToGive = getRandomXP(5, 15); const query = { userId: message.author.id, guildId: message.guild.id }; try { // 用async/await替代then,简化代码逻辑 const level = await Level.findOne(query); if (!level) { // 使用导入的Level模型作为构造函数创建新文档 const newLevel = new Level({ userId: message.author.id, guildId: message.guild.id, xp: XPToGive, level: 1 // 默认初始化等级为1,避免后续计算出错 }); await newLevel.save(); return; } level.xp += XPToGive; const requiredXP = getLevelXP(level.level); // 优化升级逻辑:保留超出的XP,而非直接清零 if (level.xp >= requiredXP) { level.xp -= requiredXP; level.level += 1; message.channel.send(`@${message.member} 升级到**Level ${level.level}**了!`); } await level.save(); } catch (error) { console.error(`[ERROR] ${error}`); } }, };
额外优化与验证
- 移除混合异步写法:不再混用
async/await和then,避免逻辑嵌套混乱 - 初始化默认字段:新增
level:1的默认值,防止未定义字段导致的计算错误 - 优化升级逻辑:升级时保留超出所需的XP,更符合常规等级系统的设计
- 模型文件验证:确保
../models/Level.js正确导出Mongoose模型,示例结构如下:
const mongoose = require('mongoose'); const levelSchema = new mongoose.Schema({ userId: { type: String, required: true }, guildId: { type: String, required: true }, xp: { type: Number, default: 0 }, level: { type: Number, default: 1 } }); module.exports = mongoose.model('Level', levelSchema);
内容的提问来源于stack exchange,提问作者Christian Ambarita
相关产品推荐
相关产品推荐

