如何在非async环境下使用Mongoose的await?Discord.js开发求助
解决“无法在async函数外使用await”的问题及替代写法
错误原因很明确:await关键字只能在标记为async的函数内部使用,你当前在模块顶层直接调用await items.find(),不符合语法规则。同时原代码里用forEach给addChoices传值也是无效的,因为forEach没有返回值,addChoices需要的是符合格式的选项数组。
以下是两种可行的解决方案:
方案1:使用ES模块的顶层await
如果你的项目可以切换为ES模块(将文件后缀改为.mjs,或在package.json中添加"type": "module"),可以直接在模块顶层使用await:
import { SlashCommandBuilder } from 'discord.js'; import items from './schema.js'; // 顶层await直接获取数据库数据 const items1 = await items.find(); export default { name: 'buy', timeout: 15000, data: new SlashCommandBuilder() .setName('buy') .setDescription('buy an item!') .addStringOption(option => option .setName('itemid') .setDescription('the item you want to buy') .setRequired(true) // 用map生成符合要求的选项数组,再展开传入addChoices .addChoices( ...items1.map(item => ({ name: `<:${item.EmojiName}:${item.EmojiID}>${item.ItemName} - <:bobux:809551218217058354>${item.Price}`, value: item.ItemID.toString() })) ) ), // 命令执行逻辑 async execute(interaction) { // 处理购买逻辑 } };
方案2:CommonJS下用异步函数导出+动态注册命令
如果需要保持CommonJS模块规范(使用require),可以将命令导出为异步函数,然后在客户端启动时(ready事件)动态加载并注册命令:
命令文件(buy.js)
const { SlashCommandBuilder } = require('discord.js'); const items = require('./schema.js'); // 导出异步函数,用于获取数据并构建命令 module.exports = async () => { const items1 = await items.find(); return { name: 'buy', timeout: 15000, data: new SlashCommandBuilder() .setName('buy') .setDescription('buy an item!') .addStringOption(option => option .setName('itemid') .setDescription('the item you want to buy') .setRequired(true) .addChoices( ...items1.map(item => ({ name: `<:${item.EmojiName}:${item.EmojiID}>${item.ItemName} - <:bobux:809551218217058354>${item.Price}`, value: item.ItemID.toString() })) ) ), async execute(interaction) { // 处理购买逻辑 } }; };
客户端启动文件
const { Client, GatewayIntentBits } = require('discord.js'); const fs = require('fs'); const path = require('path'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); client.on('ready', async () => { const commands = []; const commandFiles = fs.readdirSync(path.join(__dirname, 'commands')) .filter(file => file.endsWith('.js')); // 遍历所有命令文件,处理异步导出的命令 for (const file of commandFiles) { const commandExport = require(`./commands/${file}`); const command = typeof commandExport === 'function' ? await commandExport() : commandExport; commands.push(command.data.toJSON()); } // 注册全局命令(如果是测试服务器,可指定guildId注册到特定服务器) await client.application.commands.set(commands); console.log('所有命令已成功注册'); }); client.login('你的机器人令牌');
注意事项
- 替换
addChoices的写法:原代码用forEach无法生成addChoices需要的参数,必须用map将数据库数据转换为{name, value}格式的数组,再通过扩展运算符...传入。 - 命令注册时机:Slash命令的选项是预注册的,必须在注册时就确定
choices,无法在用户触发命令时动态生成选项。
内容的提问来源于stack exchange,提问作者FattyDev1
相关产品推荐
相关产品推荐

