You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在非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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 14:06:40