You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Deno WebSocket实现多客户端PDF创建通知广播的问题排查

Deno内置WebSocket实现组织内通知方案

服务端优化:连接管理与广播逻辑

  • 重构连接存储结构:放弃单一Map存储所有连接,改用按组织ID分组的嵌套Map,比如const orgConnections = new Map<string, Set<WebSocket>>()。每个组织对应一个独立的连接集合,新增连接时绑定用户所属的组织ID,断开时从对应集合中移除。
  • 完善WebSocket生命周期处理:
    • 客户端发起连接时,通过握手请求的URL参数(如orgId、userId)获取组织标识,验证合法性后将连接加入对应集合。
    • 监听连接的close和error事件,确保连接断开时及时从集合中清理无效连接,避免资源占用。
  • 可靠广播实现: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:54:30