如何在Node.js CLI应用中实现异步任务队列?解决bee-queue导致主进程冻结无法退出的问题
用bee-queue实现CLI提交任务后立即退出的方案
嘿,我之前也遇到过一模一样的问题!bee-queue完全能满足你的核心需求——关键是你得处理好队列的连接关闭,不然Node.js的事件循环会因为活跃的Redis连接一直挂着,导致CLI没法自动退出。
问题根源
bee-queue默认会和Redis保持持久连接,当你提交完任务后,如果不主动关闭这个连接,Node.js的事件循环会认为还有活跃的异步操作在运行,所以会一直卡住,不会终止CLI进程。
解决方案步骤
1. 提交任务后主动关闭队列连接
在你的CLI代码里,当所有任务都添加到队列后,一定要调用queue.close()来断开和Redis的连接,这样事件循环就会结束,CLI就能正常退出了。
举个完整的CLI示例代码:
const Queue = require('bee-queue'); // 初始化队列 const taskQueue = new Queue('background-tasks', { redis: { host: 'localhost', // 你的Redis地址 port: 6379, }, }); // 批量添加任务的函数 async function enqueueTasks() { try { // 模拟添加多个任务 const taskList = [ { type: 'email', recipient: 'user1@example.com' }, { type: 'report', data: 'monthly-sales' }, { type: 'cleanup', target: 'temp-files' } ]; for (const taskData of taskList) { await taskQueue.createJob(taskData).save(); console.log(`✅ 任务已加入队列: ${taskData.type}`); } // 关键操作:添加完所有任务后关闭队列连接 await taskQueue.close(); console.log("\n🎉 CLI任务提交完成,即将退出"); } catch (err) { console.error("❌ 提交任务失败:", err); // 出错时强制退出CLI process.exit(1); } } // 执行任务提交 enqueueTasks();
2. 确保Worker进程独立运行
要让队列任务在CLI退出后继续执行,你需要一个独立的Worker进程来处理队列任务——这个进程要长期运行,和CLI是分开的。
Worker示例代码(比如命名为task-worker.js):
const Queue = require('bee-queue'); const taskQueue = new Queue('background-tasks', { redis: { host: 'localhost', port: 6379, }, }); // 定义任务处理逻辑 taskQueue.process(async (job) => { console.log(`开始处理任务 [${job.id}]:${job.data.type}`); // 模拟任务耗时操作(比如发邮件、生成报告) await new Promise(resolve => setTimeout(resolve, 3000)); console.log(`任务 [${job.id}] 处理完成`); return `Result for ${job.data.type}`; }); console.log("🚀 任务Worker已启动,等待处理队列任务...");
运行流程
- 先启动Worker进程:
node task-worker.js(这个进程会一直运行,监听队列) - 运行你的CLI应用:
node your-cli-app.js——提交完任务后,CLI会自动退出,而Worker会继续处理队列里的任务
额外注意事项
- 如果是自己传入了自定义的Redis客户端实例给bee-queue,那除了调用
queue.close(),还要记得手动关闭Redis客户端,避免连接泄漏。 - 若需要确保任务至少执行一次,可以开启bee-queue的持久化配置,避免Redis重启后丢失任务。
这样就能完美实现你的需求:CLI提交任务后立即终止,后台任务由Worker继续执行~
内容的提问来源于stack exchange,提问作者Nicolas Llorca




