使用AsyncStorage实现GraphQL Subscription认证遇异步Token获取问题
解决WebSocketLink connectionParams异步获取Token发送undefined的问题
嘿,我之前也踩过类似的坑!你遇到的核心问题是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里确实存了对应的值,排除存储环节的问题。
方案2:预加载Token后再创建WebSocketLink
如果方案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
相关产品推荐
相关产品推荐

