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

React中监听ActionCable对象变化实现WebSocket断连告警

解决React中actioncable-js-jwt连接状态监听问题

问题分析

你遇到的核心问题是:仅给顶层cable对象创建Proxy无法捕获嵌套属性(connection.disconnected、connection.monitor.reconnectAttempts)的变更——因为这些属性属于嵌套对象,修改它们并不会触发顶层Proxy的set方法。

解决方案1:递归创建Proxy监听所有嵌套对象

通过递归代理cable及其所有嵌套对象,确保任何层级的属性变更都能被捕获,进而同步React状态:

1. 实现递归Proxy工具函数

const createProxy = (target, onChange) => {
  const handler = {
    get(target, property) {
      const value = target[property];
      // 对嵌套对象递归生成Proxy
      if (typeof value === 'object' && value !== null) {
        return createProxy(value, onChange);
      }
      return value;
    },
    set(target, property, value) {
      target[property] = value;
      // 属性变更时触发回调,同步React状态
      onChange();
      return true;
    }
  };

  return new Proxy(target, handler);
};

2. 在组件中使用Proxy

import { useState, useEffect } from 'react';
import { createConsumer } from 'actioncable-js-jwt';
import pathHelper from './pathHelper';

export const createCable = (token) => {
  const c = createConsumer(pathHelper('/cable'), token);
  return c;
};

const CableConnectionAlert = ({ token }) => {
  const [disconnected, setDisconnected] = useState(false);
  const [reconnectAttempts, setReconnectAttempts] = useState(0);

  // 触发告警逻辑
  useEffect(() => {
    if (disconnected && reconnectAttempts > 5) {
      alert('WebSocket连接失败,多次重连无效,请检查网络或联系管理员');
      // 也可以用自定义提示组件替代alert
    }
  }, [disconnected, reconnectAttempts]);

  useEffect(() => {
    if (!token) return;

    const cable = createCable(token);
    // 创建递归Proxy,同步状态
    const proxy = createProxy(cable, () => {
      setDisconnected(cable.connection.disconnected);
      setReconnectAttempts(cable.connection.monitor.reconnectAttempts);
    });

    // 初始化状态
    setDisconnected(proxy.connection.disconnected);
    setReconnectAttempts(proxy.connection.monitor.reconnectAttempts);

    // 组件卸载时断开连接
    return () => proxy.disconnect();
  }, [token]);

  return (
    <div>
      {disconnected && reconnectAttempts > 5 && (
        <div style={{ color: 'red', padding: '10px' }}>
          WebSocket连接异常,无法重连
        </div>
      )}
    </div>
  );
};

export default CableConnectionAlert;

解决方案2:利用ActionCable内置事件(更简洁)

ActionCable本身提供了连接状态的回调事件,直接监听这些事件来更新状态,无需手动监听对象属性:

const CableConnectionAlert = ({ token }) => {
  const [disconnected, setDisconnected] = useState(false);
  const [reconnectAttempts, setReconnectAttempts] = useState(0);

  useEffect(() => {
    if (disconnected && reconnectAttempts > 5) {
      alert('WebSocket连接失败,多次重连无效');
    }
  }, [disconnected, reconnectAttempts]);

  useEffect(() => {
    if (!token) return;

    const cable = createCable(token);
    const connection = cable.connection;

    // 监听连接成功事件
    const handleConnected = () => {
      setDisconnected(false);
      setReconnectAttempts(0);
    };

    // 监听断开事件
    const handleDisconnected = () => {
      setDisconnected(true);
    };

    // 定时同步重连尝试次数(因为monitor.reconnectAttempts是自动更新的)
    const interval = setInterval(() => {
      setReconnectAttempts(connection.monitor.reconnectAttempts);
    }, 1000);

    // 绑定事件
    connection.addEventListener('connected', handleConnected);
    connection.addEventListener('disconnected', handleDisconnected);

    // 初始化状态
    setDisconnected(connection.disconnected);
    setReconnectAttempts(connection.monitor.reconnectAttempts);

    // 清理资源
    return () => {
      clearInterval(interval);
      connection.removeEventListener('connected', handleConnected);
      connection.removeEventListener('disconnected', handleDisconnected);
      cable.disconnect();
    };
  }, [token]);

  return (
    <div>
      {disconnected && reconnectAttempts > 5 && (
        <div style={{ color: 'red', padding: '10px' }}>
          WebSocket连接异常,无法重连
        </div>
      )}
    </div>
  );
};

方案对比

  • 递归Proxy:实时捕获属性变更,无延迟,但需要处理嵌套对象的代理逻辑,代码稍复杂。
  • 内置事件+定时检查:代码更简洁,符合ActionCable的设计规范,重连次数的定时检查有轻微延迟,但完全满足告警需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:15:28