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

NestJS路由内连接WebSocket遭遇XHR Polling Error问题求助

解决NestJS路由中动态连接外部WebSocket的XHR Polling Error问题

问题分析

XHR Polling Error通常是Socket.IO客户端与服务端协议不兼容、客户端配置不合理,或者代码中Promise/事件监听处理不当导致的连接异常。结合你的代码,核心问题包括:

  • Socket.IO默认优先尝试XHR Polling作为 fallback,若服务端不支持或网络受限就会触发报错
  • 代码中Promise类型定义与实际返回值不符,且未在连接完成后及时清理资源
  • 事件监听未做完整的异常兜底,可能导致连接残留

修正后的代码

import { Socket } from 'socket.io-client';
import { io } from 'socket.io-client';

async function connectAndFetchData(websocketUrl: string): Promise<string> {
  if (!websocketUrl) {
    throw new Error("Websocket connection failed.");
  }

  // 初始化Socket,强制优先使用WebSocket协议,跳过XHR Polling尝试
  const socket: Socket = io(websocketUrl, {
    secure: true,
    reconnection: true,
    rejectUnauthorized: false,
    transports: ['websocket'],
    reconnectionAttempts: 3, // 限制重连次数,避免无限等待
  });

  try {
    // 等待连接成功
    await new Promise<void>((resolve, reject) => {
      socket.on("connect", () => {
        console.log("connected");
        resolve();
      });
      socket.on("connect_error", (error: Error) => {
        reject(new Error(`连接失败: ${error.message}`));
      });
      socket.on("connect_timeout", () => {
        reject(new Error("连接超时"));
      });
    });

    // 等待目标消息返回
    return new Promise<string>((resolve, reject) => {
      const cleanup = () => {
        socket.off("onMessage");
        socket.off("error");
        socket.off("disconnect");
        socket.disconnect(); // 主动关闭连接,释放资源
      };

      socket.on("onMessage", (data: any) => {
        console.log(data);
        cleanup();
        try {
          if (data.type === "failed") {
            reject(new Error("请求失败"));
          } else {
            const stringData = data.payload.redirect;
            console.log(stringData);
            resolve(stringData);
          }
        } catch (err) {
          reject(err);
        }
      });

      socket.on("error", (error: Error) => {
        cleanup();
        reject(new Error(`Websocket错误: ${error.message}`));
      });

      socket.on("disconnect", () => {
        cleanup();
        reject(new Error("Websocket连接已关闭"));
      });
    });
  } catch (err) {
    socket.disconnect(); // 异常时确保关闭连接
    throw err;
  }
}

关键优化点

  • 强制WebSocket协议:通过transports: ['websocket']跳过XHR Polling的尝试,直接使用WebSocket协议,从根源避免XHR Polling Error
  • 资源清理:新增cleanup函数,在所有resolve/reject路径中清理事件监听并主动断开连接,防止内存泄漏
  • 完善异常处理:补充connect_timeout事件监听,覆盖更多连接失败场景
  • 类型修正:将返回Promise的类型从void改为string,匹配实际返回值

额外排查建议

  1. 版本兼容性:确认外部WebSocket服务使用的Socket.IO版本与你的客户端版本(socket.io-client)一致,版本不匹配会导致握手失败
  2. URL有效性:检查websocketUrl是否包含正确的路径(部分服务端需要指定命名空间,如wss://example.com/ws)
  3. 网络环境:确认NestJS服务所在环境能正常访问外部WebSocket端点,无防火墙、代理拦截WebSocket流量
  4. 服务端事件名:验证服务端实际发送的事件名是否为onMessage,事件名不匹配会导致无法接收消息

内容的提问来源于stack exchange,提问作者stud1234

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:23:22