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

Flutter中GraphQL订阅连接异常问题求助

Flutter GraphQL订阅连接立即断开问题排查

问题概述

使用graphql: ^5.1.3包开发Flutter应用时,查询和Mutation功能正常,但订阅功能无法工作。日志显示WebSocket连接建立后立即断开,订阅返回错误事件。

客户端代码

@Singleton()
class GraphQlClient {
  GraphQLClient? client;

  void init() {
    _initConnection();
  }

  void _initConnection() async {
    final graphQlHost = UrlTool.graphQlUrl();
    final subscriptionQlHost = UrlTool.subscriptionUrl();
  
    final token = getIt<LoginCubit>().state.userToken;
    
    logger.i('init basic connection');
    logger.i(token);
    
    final httpLink = HttpLink(graphQlHost);

    final AuthLink authLink = AuthLink(
      getToken: () async {
        final sharedPref = await SharedPreferences.getInstance();
        final token = sharedPref.getString(kMerchantToken);
        return token == null ? null : 'Bearer $token';
      },
    ); // 安全获取token
    final link = Link.split(
      (request) => request.isSubscription,
      WebSocketLink(
        subscriptionQlHost,
        config: SocketClientConfig(
          initialPayload: {'Authorization': 'Bearer $token'}, // 为WebSocketLink添加token
        ),
      ),
      authLink.concat(httpLink),
    );

    client = GraphQLClient(
      link: link,
      cache: GraphQLCache(),
      defaultPolicies: DefaultPolicies(
        watchMutation: Policies(fetch: FetchPolicy.networkOnly),
        watchQuery: Policies(fetch: FetchPolicy.networkOnly),
        query: Policies(fetch: FetchPolicy.networkOnly),
        mutate: Policies(fetch: FetchPolicy.networkOnly),
        subscribe: Policies(fetch: FetchPolicy.networkOnly),
      ),
    );
  }
}

订阅监听代码

getIt<GraphQlClient>()
        .client
        ?.subscribe$OrderUpdated(
          Options$Subscription$OrderUpdated(
            fetchPolicy: FetchPolicy.networkOnly,
            variables:
                Variables$Subscription$OrderUpdated(id: getIt<TabletChooserCubit>().state.selectedTablet?.id ?? ''),
          ),
        )
        .listen(_updateOrders);

日志信息

I/flutter (12107): Connected to websocket.
I/flutter (12107): Initialising connection
I/flutter (12107): Disconnected from websocket.

订阅错误事件

订阅错误事件截图

排查方向与解决方案

  • WebSocket Token一致性问题:
    当前WebSocketLink的initialPayload使用的是LoginCubit同步获取的token,而AuthLink是异步从SharedPreferences取的token,两者可能存在不一致(比如LoginCubit的token未更新)。建议WebSocketLink也改用异步方式获取最新token:

    WebSocketLink(
      subscriptionQlHost,
      config: SocketClientConfig(
        initialPayload: () async {
          final sharedPref = await SharedPreferences.getInstance();
          final token = sharedPref.getString(kMerchantToken);
          return {'Authorization': token == null ? '' : 'Bearer $token'};
        },
      ),
    ),
    
  • WebSocket URL协议正确性:
    确认subscriptionQlHost使用的是WebSocket协议(ws://或wss://),而非HTTP协议(http://或https://),协议不匹配会导致连接立即断开。

  • 客户端初始化时机问题:
    _initConnection是异步函数,但init()未等待其完成就可能执行订阅,导致client未初始化完全。修改init()为异步函数:

    Future<void> init() async {
      await _initConnection();
    }
    

    调用时先等待初始化完成再执行订阅:

    await getIt<GraphQlClient>().init();
    // 后续执行订阅逻辑
    
  • 后端订阅参数与配置问题:
    错误截图显示Cannot read properties of undefined (reading '0'),大概率是后端处理订阅请求时解析参数出错。检查传入的id是否为空字符串(selectedTablet?.id为空时会传空值),后端是否接受空id;同时确认后端已正确配置WebSocket支持,允许客户端Origin访问,且OrderUpdated订阅字段存在并配置正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 13:41:35