Discord bot开发中如何让异步函数等待模块cache属性初始化完成
问题原因
你遇到的this.cache为undefined的问题核心是this指向错误,而非缓存未初始化:
- 你在
execute方法内部定义的getPrefix是普通异步函数,普通函数的this指向调用它的上下文,这里默认是全局对象(非严格模式下)或者undefined(严格模式下),自然无法指向你导出的模块对象上的cache属性。 - 你导出模块上的
cache是随模块初始化就创建的空对象,不需要额外等待初始化。
修复方案
方案1:修正this指向(最快修复)
把getPrefix改为箭头函数,箭头函数的this会继承外层作用域(也就是execute方法的this,而execute作为模块方法调用时this指向导出的模块对象),就能正常访问cache:
const common = require('../util/common'); const Discord = require('discord.js'); const math = require('mathjs'); const guildSettings = require('../schema/guildSchema'); module.exports = { name: "test2", description: "a test command!", usage: `\`${process.env.PREFIX}test2\``, category: "Admin", alias: ["test2"], disabled: false, cache: {}, async execute(message, args){ // 改为箭头函数继承外层this const getPrefix = async () => { if (!this.cache[message.guild.id]){ let settings = await guildSettings.findOne({ _id: message.guild.id }); if (!settings){ settings = await guildSettings.create({ _id: message.guild.id, prefix: '-', }); await settings.save(); } this.cache[message.guild.id] = settings.prefix; return this.cache[message.guild.id]; } else { return this.cache[message.guild.id]; } } let prefix = await getPrefix(); message.reply(` your prefix is ${prefix}`); } }
方案2:预加载缓存(更优体验)
如果要完全避免首次调用命令时查询数据库的延迟,可以在bot的ready事件中预加载所有服务器的前缀到缓存中:
- 把缓存提取到公共的工具模块,方便入口文件和命令共同访问
- 在bot启动完成触发
ready事件时,批量查询所有guild的配置,一次性写入缓存
额外优化
如果同一时间有多个相同guild的命令触发,可能会导致重复查询数据库,可以给每个guild的查询加个pending状态锁,避免重复请求。
内容的提问来源于stack exchange,提问作者Myssto
相关产品推荐
相关产品推荐

