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
相关产品推荐
相关产品推荐

