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

Discord.js+Express跨文件传递client变量报错如何解决

问题原因

报错是CommonJS模块循环依赖+导出/导入顺序错误导致的,和client是否完成登录初始化无关:

  • 你在index.js中创建client实例后,先执行require('./routes.js')加载路由
  • 路由文件加载时会反向require('./index.js'),但此时index.js还没运行到module.exports = { client }这一行,路由文件拿到的导出对象是空值,最终传入vote.js的client是undefined
  • 读取undefined.users.cache自然会抛出类型错误。

另外你直接读client.users.cache也有隐患:如果目标用户不在本地缓存里,哪怕client实例正常,也会拿到undefined导致发消息失败。

修复方法

方案1:调整代码顺序(改动最小)

  1. 把index.js里的client导出语句,移到加载路由文件之前,确保路由加载时能拿到正确的导出值:
// index.js
const client = new Client(/* 你的客户端配置,比如intents等 */);
// 提前导出client,再加载路由
module.exports = { client };

const routes = require('./routes.js');
https.createServer(options, app).listen(PORT, function() {
    console.log('Express server listening on port ' + PORT);
});
app.use(bodyParser.json(), routes, limiter);
client.login(token).then(() => {console.info('Logged in.');});
  1. 修改routes.js的导入方式,不要在加载时直接解构client,避免CommonJS值拷贝导致拿不到最终实例:
// routes.js
const express = require('express');
const router = express.Router();
const { invite, topggAuth } = require('./config.json');
// 导入整个index模块对象,不要提前解构client
const appModule = require('./index.js');
const vote = require('./events/vote.js');

router.route('/api/tggwh').post((req, res) => {
    if (req.header('authorization') === topggAuth) {
        // 请求处理时再取client属性,确保拿到有效实例
        vote.execute(appModule.client, req.body);
        res.status(200).end();
    }
    else {
        console.log('Unauthorized vote request attempt.');
        res.status(401).send('Unauthorized').end();
    }
});

module.exports = router;
  1. 优化vote.js的用户获取逻辑,不要强依赖本地缓存:
// vote.js
const { logUsage } = require('../functions.js');

module.exports = {
    name: 'vote',
    async execute(client, data) {
        try {
            // 用fetch方法拉取用户,自动处理缓存未命中的情况
            const targetUser = await client.users.fetch(data.user);
            await targetUser.send('Thank you for voting!');
            logUsage({ name: 'vote' });
        }
        catch (error) {
            console.error('Whoops! Something went wrong while thanking a vote.');
            console.error(error);
        }
    },
};

方案2:抽离client实例(彻底规避循环依赖)

如果不想调整现有代码顺序,可以单独新建client.js文件专门维护客户端实例,从根源消除循环引用:

// client.js
const { Client } = require('discord.js');
// 单独初始化并导出client
const client = new Client(/* 你的客户端配置 */);
module.exports = client;

之后index.js、routes.js、vote.js全部从这个独立文件导入client即可,不会再出现加载顺序导致的取值错误。

优化建议:可以等client触发ready事件后再启动HTTP服务,避免服务刚启动、客户端还没完成Discord连接时收到请求,导致接口调用失败。

内容的提问来源于stack exchange,提问作者johng3587

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:36:14