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

discord.js 14.11.0机器人仅本地可用,部署后异常离线问题咨询

问题分析与解决方案

你的问题根源在于每次按钮点击都重复创建Discord客户端并登录,这在Vercel的无服务器函数环境下会触发Discord的连接限制,同时无服务器的冷启动/实例销毁机制也会导致后续请求失效。

为什么本地正常,Vercel异常?

  • 本地是持续运行的Node.js进程,每次创建客户端后连接会保持,重复登录虽然不规范,但短时间内不会触发限制。
  • Vercel的无服务器函数是按需启动、用完即销毁的:
    • 首次点击时,函数启动并初始化客户端,这需要建立Discord网关连接,所以有10秒延迟;
    • 函数执行完后实例被销毁,客户端连接断开,机器人显示离线;
    • 后续点击会启动新的函数实例,再次创建客户端登录,但Discord会拒绝频繁重复的连接请求,导致无响应;
    • 本地点击时用的是另一个持续运行的客户端,重新建立了连接,所以机器人又显示在线,但Vercel的新实例还是会被限制。

必须用单例模式初始化客户端

没错,你需要采用单例模式,仅在函数冷启动时初始化并登录一次Discord客户端,后续所有点击请求复用这个已连接的实例。

修改后的代码示例(以Vercel API路由为例)

// 全局作用域,仅在函数冷启动时执行一次
const { Client, GatewayIntentBits } = require('discord.js');
let discordClient;

async function getDiscordClient() {
  if (!discordClient) {
    discordClient = new Client({ intents: [GatewayIntentBits.Guilds] });
    // 监听ready事件,确保客户端登录完成
    await new Promise(resolve => discordClient.once('ready', resolve));
    await discordClient.login(MY_BOT_TOKEN);
  }
  return discordClient;
}

// API路由处理函数
export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).send('Method Not Allowed');
  }

  try {
    const client = await getDiscordClient();
    const discordUser = await client.users.fetch('1234567890');
    await discordUser.send({ 
      content: 'hello world', 
      files: [{ attachment: 'image.png' }] 
    });
    res.status(200).send('Message sent successfully');
  } catch (error) {
    console.error('Error sending message:', error);
    res.status(500).send('Failed to send message');
  }
}

额外注意事项

  • 确保客户端的intents配置正确,发送私信不需要额外的意图,但如果需要处理用户相关事件可能需要调整;
  • 处理客户端的重连逻辑:如果Discord网关连接断开,客户端会自动重连,但要确保单例实例能正确恢复;
  • Vercel函数有超时限制(默认10秒),如果发送大文件可能需要调整超时时间,或者优化文件传输方式;
  • 避免在客户端初始化时执行过多操作,尽量让冷启动时间缩短。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:55:08