Redux Toolkit Query GraphQL订阅无法运行,请求技术帮助
解决RTK Query + GraphQL订阅的
subscriptions are not supported over HTTP错误 问题根源
你用builder.query定义订阅时,RTK Query会默认通过HTTP POST请求发送这个GraphQL Subscription操作,但GraphQL订阅只能通过WebSocket协议处理,因此服务器返回错误提示。
修复方案
1. 拆分初始数据查询与订阅逻辑
用普通的GraphQL Query通过HTTP获取初始数据,再在onCacheEntryAdded中建立WebSocket连接处理订阅更新,避免RTK Query发送HTTP请求执行Subscription操作。
2. 修改后的代码示例
userStatus: builder.query< UserStatusQueryResult, // 替换为你的普通查询返回类型 { event_id: string; user_id: string } >({ // 用普通Query获取初始数据,而非Subscription query: ({ event_id, user_id }) => ({ document: gql` query GetUserStatus($event_id: uuid!, $user_id: String!) { eetschema_event_by_pk(id: $event_id) { event_attendees(where: { user_id: { _eq: $user_id } }) { status event_id user_id } } } `, variables: { event_id, user_id }, }), async onCacheEntryAdded( arg, { updateCachedData, cacheDataLoaded, cacheEntryRemoved } ) { // 连接GraphQL WebSocket端点(根据你的服务器配置调整路径) const ws = new WebSocket("ws://localhost:8080/graphql"); let resolveConnection: () => void; const connectionReady = new Promise<void>(res => resolveConnection = res); // 连接建立后发送订阅请求 ws.onopen = () => { ws.send(JSON.stringify({ type: "start", id: "user-status-sub-1", payload: { query: ` subscription UserStatusSubscription($event_id: uuid!, $user_id: String!) { eetschema_event_by_pk(id: $event_id) { event_attendees(where: { user_id: { _eq: $user_id } }) { status event_id user_id } } } `, variables: arg } })); resolveConnection(); }; try { // 等待初始数据缓存完成 + WebSocket连接就绪 await cacheDataLoaded; await connectionReady; const handleMessage = (event: MessageEvent) => { const message = JSON.parse(event.data); // 处理服务器返回的订阅数据(格式根据你的服务器调整) if (message.type === "data" && message.id === "user-status-sub-1") { updateCachedData((draft) => { // 正确修改Immer draft,不能直接赋值 draft.eetschema_event_by_pk = message.payload.data.eetschema_event_by_pk; }); } }; ws.addEventListener("message", handleMessage); } catch { // 忽略缓存提前销毁的异常 } // 缓存订阅结束时清理WebSocket连接 await cacheEntryRemoved; ws.send(JSON.stringify({ type: "stop", id: "user-status-sub-1" })); ws.close(); }, }),
3. 额外注意事项
- 确认你的GraphQL服务器已配置WebSocket订阅支持(比如使用
graphql-ws或subscriptions-transport-ws库)。 - WebSocket消息格式需匹配服务器要求(示例使用的是
graphql-ws的标准格式,若你用的是旧版subscriptions-transport-ws,格式会有差异)。 - 更新缓存时必须修改Immer draft的属性,不能直接替换整个draft对象,否则RTK Query无法跟踪缓存变更。
内容的提问来源于stack exchange,提问作者Wiezalditzijn
相关产品推荐
相关产品推荐

