基于Deno WebSocket实现多客户端PDF创建通知广播的问题排查
Deno内置WebSocket实现组织内通知方案
服务端优化:连接管理与广播逻辑
- 重构连接存储结构:放弃单一Map存储所有连接,改用按组织ID分组的嵌套Map,比如
const orgConnections = new Map<string, Set<WebSocket>>()。每个组织对应一个独立的连接集合,新增连接时绑定用户所属的组织ID,断开时从对应集合中移除。 - 完善WebSocket生命周期处理:
- 客户端发起连接时,通过握手请求的URL参数(如
orgId、userId)获取组织标识,验证合法性后将连接加入对应集合。 - 监听连接的
close和error事件,确保连接断开时及时从集合中清理无效连接,避免资源占用。
- 客户端发起连接时,通过握手请求的URL参数(如
- 可靠广播实现:PDF生成完成后,根据目标组织ID找到对应的连接集合,遍历发送时捕获异常(处理已失效但未清理的连接),代码示例:
function broadcastToOrg(orgId: string, message: string) { const connections = orgConnections.get(orgId); if (!connections) return; for (const ws of connections) { if (ws.readyState === WebSocket.OPEN) { try { ws.send(message); } catch (err) { console.error("消息发送失败:", err); connections.delete(ws); } } else { connections.delete(ws); } } }
客户端优化:避免重复连接与状态同步
- 单例WebSocket实例:用单例模式管理客户端Socket连接,避免重复初始化,示例代码:
class SocketManager { static instance; ws; orgId; constructor(orgId) { if (SocketManager.instance) return SocketManager.instance; this.orgId = orgId; this.connect(); SocketManager.instance = this; } connect() { this.ws = new WebSocket(`ws://你的服务地址/ws?orgId=${this.orgId}`); this.ws.onmessage = (event) => { const data = JSON.parse(event.data); if (data.type === "pdf-ready") { updateNotificationCount(); } }; // 断线自动重连 this.ws.onclose = () => setTimeout(() => this.connect(), 3000); } } // 页面初始化时调用 new SocketManager(currentUserOrgId); - 跨标签页状态同步:利用浏览器
Broadcast Channel API实现标签页间通知数同步,示例:// 收到Socket消息更新计数时 function updateNotificationCount() { let count = parseInt(localStorage.getItem("notificationCount") || "0") + 1; localStorage.setItem("notificationCount", count.toString()); // 更新当前页面UI document.getElementById("notification-badge").textContent = count; // 广播给其他标签页 const channel = new BroadcastChannel("notification-sync"); channel.postMessage({ type: "count-update", count }); } // 监听其他标签页的同步消息 const syncChannel = new BroadcastChannel("notification-sync"); syncChannel.onmessage = (event) => { if (event.data.type === "count-update") { document.getElementById("notification-badge").textContent = event.data.count; } };
常见问题排查
- 第二次点击无Socket返回:检查服务端PDF生成完成后是否正确触发广播逻辑,以及连接是否因异常被清理未重新加入;同时确认客户端Socket是否因断线未执行重连。
- 新标签页收不到通知:确保新标签页初始化时正确获取组织ID并加入对应连接集合,同时通过广播API同步已有的通知计数。
内容的提问来源于stack exchange,提问作者Ömer Faruk
相关产品推荐
相关产品推荐

