discord.js扩展系统开发:for循环读取JSON模块报mod.commands不可迭代问题
报错根因
mod.commands isn't iterable的本质原因是:mod.commands是键值对形式的普通JS对象(结构为{命令名: 命令文件地址}),而for...of循环仅支持遍历数组、Map、Set等原生可迭代对象,无法直接遍历普通对象的属性,因此触发类型错误。
除此之外原代码还存在几处关联逻辑bug,会在遍历修正后继续触发报错:
- 变量引用错误:循环中拿到的
module是fs.readdirSync返回的文件名字符串(如user_module.json),不是require解析后的模块对象,原代码写的module.name根本无法取到JSON里定义的模块名 - 数据库判断逻辑错误:原代码只在数据库存单个模块名,一旦命中判断就直接
return中断整个循环,会跳过后续所有未处理的模块 - 未定义变量引用:download方法调用时传入了未定义的
error变量作为回调
可直接运行的修正方案
- 使用
Object.entries()将普通对象转为可迭代的键值对数组,适配for...of遍历 - 修正模块名的变量引用,用解析后的模块对象
mod取name字段 - 调整已解析模块的存储逻辑,用数组存储所有已处理的模块名,遍历过程中跳过已解析项
- 补全download方法的错误回调,避免引用未定义变量
修正后的loadExt函数代码
function loadExt(){ const moduleFiles = fs.readdirSync(`./modules`).filter(file => file.endsWith('.json')); // 初始化读取数据库中已解析的模块列表,没有则默认空数组 const parsedModules = db.get('parsedModules') || []; for (const moduleFileName of moduleFiles){ // 跳过已经解析过的模块 if (parsedModules.includes(moduleFileName)) continue; // 解析模块JSON内容 const mod = require(`./modules/${moduleFileName}`) // 遍历commands对象的[命令名, 命令地址]键值对 for (const [commandName, commandUrl] of Object.entries(mod.commands)){ download( commandUrl, `./commands/ext/${mod.name}/${commandName}.js`, (err) => { if (err) console.error(`模块 ${mod.name} 的命令 ${commandName} 加载失败:`, err); } ); } // 将处理完成的模块加入已解析列表,写回数据库 parsedModules.push(moduleFileName); db.set('parsedModules', parsedModules); } }
内容的提问来源于stack exchange,提问作者Anden Wieseler
相关产品推荐
相关产品推荐

