如何在Discord.js中用Bull、Throng、Redis运行Worker并返回任务结果
解决Discord Bot + Heroku + Bull队列的核心问题
一、如何运行Worker文件执行繁重任务
本地测试运行
打开两个终端窗口分别启动进程:
- 启动Discord Bot主进程:
node index.js - 启动Worker队列处理进程:
node worker.js
Heroku部署后运行
- 创建Procfile:在项目根目录新建名为
Procfile(首字母大写,无文件后缀)的文件,写入内容:
web: node index.js worker: node worker.js
web进程负责监听Discord命令、向队列添加任务worker进程负责执行爬取等繁重任务
- 启动Worker Dyno:
- 命令行方式:执行
heroku ps:scale worker=1(数字1代表启动1个worker进程,可按需调整数量) - 后台操作方式:登录Heroku应用后台→进入
Resources页面,找到worker进程,开启开关并设置进程数
- 命令行方式:执行
二、获取任务返回值并发送给Discord用户
当前global:completed事件仅能拿到任务ID和结果,无法关联触发任务的用户。解决核心是添加任务时存入用户/交互的关键信息,任务完成后通过这些信息定位用户并发送结果。
修改主进程代码(index.js)
client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return const {commandName} = interaction if (commandName === 'views') { // 存入用户ID、频道ID、交互token等关键信息 const jobData = { userId: interaction.user.id, channelId: interaction.channelId, interactionToken: interaction.token, // 用于编辑之前的回复 text: 'Running...' } await workQueue.add('process', jobData) await interaction.reply(`processing... 结果完成后会通知你`) } }) // 监听任务完成事件 workQueue.on('global:completed', async (jobId, result) => { // 根据任务ID获取完整任务数据 const job = await workQueue.getJob(jobId) if (!job) return const {userId, channelId, interactionToken} = job.data const channel = client.channels.cache.get(channelId) if (!channel) return // 方式1:直接在频道@用户发送结果 await channel.send(`<@${userId}> 你的爬取任务完成!结果:${JSON.stringify(result)}`) // 方式2:编辑之前的回复(替代单独发送消息) // await client.rest.interactions.editReply(interactionToken, `任务完成!结果:${JSON.stringify(result)}`) })
完善Worker进程的爬取逻辑(worker.js)
将测试代码替换为实际爬取逻辑:
workQueue.process(maxJobsPerWorker, async job => { console.log(`开始处理任务 ${job.id}`) // 替换为你的实际爬取函数 const scrapeResult = await yourScrapingFunction(job.data.text) // 返回爬取结果,供主进程的global:completed事件捕获 return { jobId: job.id, scrapeData: scrapeResult } })
额外注意事项
- Redis配置:Heroku环境需安装Heroku Redis插件,本地测试使用本地Redis服务
- 错误处理:可添加
global:failed事件监听任务失败,及时通知用户 - 进程调整:根据任务量通过
heroku ps:scale worker=N调整worker进程数 - 任务持久化:Bull将任务存储在Redis中,即使Heroku Dyno重启,未完成任务也不会丢失
内容的提问来源于stack exchange,提问作者Alaa
相关产品推荐
相关产品推荐

