如何创建并后台管理多个whatsapp-web.js客户端实例?
实现多WhatsApp客户端实例的后台管理方案
核心思路
用全局Map对象缓存已创建的WhatsappWebSession实例,以client-id作为键实现快速查询与复用,彻底解决重复创建销毁带来的性能损耗。同时修改原类的硬编码配置,让每个实例对应独立的会话数据,避免冲突。
步骤1:修改WhatsappWebSession类
将硬编码的clientId和dataPath改为构造函数参数,让每个实例支持独立配置:
import { Client, LocalAuth } from "whatsapp-web.js"; class WhatsappWebSession { constructor(clientId, qrCallback, readyCallback) { this.clientId = clientId; this.client = new Client({ puppeteer: { headless: true, args: ['--no-sandbox'] }, authStrategy: new LocalAuth({ clientId: clientId, // 每个client-id对应独立的会话目录,防止数据冲突 dataPath: `./sessions/${clientId}` }) }); this.client.on('qr', (qr) => { this.qr = qr; qrCallback(qr, clientId); }); this.client.on('ready', () => { console.log(`Client ${clientId} is ready!`); readyCallback(clientId); }); this.client.initialize(); } getQr() { return this.qr; } getClient() { return this.client; } async destroy() { await this.client.destroy(); console.log(`Client ${this.clientId} destroyed`); } async restart() { await this.destroy(); // 重启时复用当前实例的clientId配置 this.client = new Client({ puppeteer: { headless: true, args: ['--no-sandbox'] }, authStrategy: new LocalAuth({ clientId: this.clientId, dataPath: `./sessions/${this.clientId}` }) }); this.client.on('qr', (qr) => { this.qr = qr; }); this.client.initialize(); } } export default WhatsappWebSession;
注意:提前创建
./sessions目录,用于存储不同client-id的会话数据。
步骤2:Express端实例管理
创建全局Map存储实例,在接口中处理创建、查询、销毁逻辑:
import express from 'express'; import WhatsappWebSession from './whatsappWebSession.js'; const app = express(); // 全局缓存容器:key=client-id,value=WhatsappWebSession实例 const clientSessions = new Map(); // 创建/查询客户端实例接口 app.get('/new-client', async (req, res) => { const { id: clientId } = req.query; if (!clientId) { return res.status(400).send('缺少client-id参数'); } // 已有实例直接返回状态 if (clientSessions.has(clientId)) { const session = clientSessions.get(clientId); return res.json({ status: '已存在', clientId, isReady: session.getClient().ready, qr: session.getQr() }); } // 无实例则创建新实例 let qrCode = null; let isReady = false; const session = new WhatsappWebSession( clientId, // QR码生成回调 (qr, id) => { qrCode = qr; console.log(`客户端${id}生成QR码: ${qr}`); }, // 客户端就绪回调 (id) => { isReady = true; console.log(`客户端${id}已就绪`); } ); // 存入全局缓存 clientSessions.set(clientId, session); res.json({ status: '已创建', clientId, qr: qrCode, isReady }); }); // 通过client-id获取指定客户端接口 app.get('/get-client', (req, res) => { const { id: clientId } = req.query; if (!clientId) { return res.status(400).send('缺少client-id参数'); } const session = clientSessions.get(clientId); if (!session) { return res.status(404).send('未找到该客户端'); } res.json({ clientId, isReady: session.getClient().ready, qr: session.getQr() }); }); // 销毁指定客户端实例接口 app.post('/destroy-client', async (req, res) => { const { id: clientId } = req.query; if (!clientId) { return res.status(400).send('缺少client-id参数'); } const session = clientSessions.get(clientId); if (!session) { return res.status(404).send('未找到该客户端'); } await session.destroy(); clientSessions.delete(clientId); res.json({ status: '已销毁', clientId }); }); app.listen(3000, () => { console.log('服务运行在端口3000'); });
关键优化点
- 实例复用:通过Map缓存避免重复初始化WhatsApp客户端,大幅提升接口响应速度;
- 独立会话存储:每个client-id对应单独的会话目录,彻底解决会话数据冲突问题;
- 生命周期可控:提供销毁接口,可手动清理实例,也可扩展闲置超时自动销毁逻辑;
- 状态实时反馈:通过回调跟踪实例的QR生成和就绪状态,方便前端同步信息。
额外建议
- 若需实时推送QR码或就绪状态,可引入WebSocket(如socket.io)替代轮询,提升交互效率;
- 生产环境建议将会话目录路径配置为环境变量,方便容器化部署;
- 可添加实例健康检查逻辑,自动重启异常离线的客户端。
内容的提问来源于stack exchange,提问作者himanshu saini
相关产品推荐
相关产品推荐

