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

使用AsyncStorage实现GraphQL Subscription认证遇异步Token获取问题

嘿,我之前也踩过类似的坑!你遇到的核心问题是WebSocketLink建立连接时,没能正确等待async版connectionParams函数完成异步操作,直接把未resolved的异步结果发给了服务器,所以才出现undefined。下面给你几个靠谱的解决方案:

方案1:修正async版connectionParams的写法

先确保你的connectionParams是一个返回Promise的async函数,并且正确从AsyncStorage取到值后返回完整对象——很多时候问题出在没正确await或者返回值缺失:

const wsLink = new WebSocketLink({
  uri: wsUri,
  options: {
    reconnect: true,
    // 必须是async函数,返回包含token的参数对象
    connectionParams: async () => {
      // 正确await AsyncStorage的获取操作
      const jwtToken = await AsyncStorage.getItem('jwtToken');
      const refreshToken = await AsyncStorage.getItem('refreshToken');
      
      // 一定要返回完整对象,避免undefined
      return {
        authorization: jwtToken ? `Bearer ${jwtToken}` : '',
        refreshToken: refreshToken || ''
      };
    }
  }
});

可以在函数里加个console.log(jwtToken, refreshToken),先确认AsyncStorage里确实存了对应的值,排除存储环节的问题。

如果方案1还是不行,可能是某些版本的Apollo Client对异步connectionParams的支持有问题。这时候可以先异步拿到Token,再创建WebSocketLink:

// 封装异步初始化WebSocketLink的函数
const createWebSocketLink = async () => {
  // 用Promise.all并行获取,提升效率
  const [jwtToken, refreshToken] = await Promise.all([
    AsyncStorage.getItem('jwtToken'),
    AsyncStorage.getItem('refreshToken')
  ]);

  return new WebSocketLink({
    uri: wsUri,
    options: {
      reconnect: true,
      connectionParams: {
        authorization: jwtToken ? `Bearer ${jwtToken}` : '',
        refreshToken: refreshToken || ''
      }
    }
  });
};

// 异步初始化Apollo Client
const initApolloClient = async () => {
  const wsLink = await createWebSocketLink();
  const httpLink = new HttpLink({ uri: httpUri });

  // 区分订阅和查询/突变的链路
  const splitLink = split(
    ({ query }) => {
      const definition = getMainDefinition(query);
      return (
        definition.kind === 'OperationDefinition' &&
        definition.operation === 'subscription'
      );
    },
    wsLink,
    httpLink
  );

  return new ApolloClient({
    link: splitLink,
    cache: new InMemoryCache()
  });
};

// 在App启动时调用初始化
const client = await initApolloClient();

这种方式先确保Token已获取完成,再创建链路,从根源避免异步时机冲突。

方案3:动态更新Token(可选)

如果你的应用需要在Token刷新后更新WebSocket连接参数,方案1的写法其实已经支持这个场景——每次重连时,async函数都会重新从AsyncStorage获取最新的Token。如果需要更主动的更新,可以结合Apollo的setContext机制,但一般方案1就足够覆盖需求。

额外检查点

  • 确认你的@apollo/client或subscriptions-transport-ws是较新版本,旧版本可能不支持异步的connectionParams函数。
  • 排查服务器端是否正确解析connectionParams,有时候问题不在前端发送,而是后端接收逻辑有误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:35:29