如何在 apollo 客户端中检测订阅(websocket)的断开连接和重新连接

How to detect disconnect and reconnect for subscription(websocket) in apollo client

我正在构建聊天服务,我想处理订阅(websocket)连接断开的情况。 Apollo 客户端配置如下。我删除了缓存、authLink 等不必要的代码

我该如何使用 React,apollo 客户端?如果它断开连接,我想将其显示到聊天页面,当用户重新连接时,我想获取所有错过的聊天消息。这就是为什么我需要知道断开连接、连接事件

以下是此应用中使用的相关包:

"@apollo/client": "^3.3.7",
"subscriptions-transport-ws": "^0.9.18",
"react": "^17.0.1"
const httpLink = new BatchHttpLink({ uri: config.API_URL })
const wsLink = new WebSocketLink({
  uri: config.WS_URL,
  options: {
    reconnect: true,
    connectionParams:{       
      authToken: accessToken,
    },
  },
})

const splitLink = split(
  ({ query }) => {
    const definition = getMainDefinition(query) 
    return definition.kind === 'OperationDefinition' && definition.operation === 'subscription'
  },
  wsLink,
  httpLink
)
const client = new ApolloClient({
  cache,
  link: from([new SentryLink(), authLink, errorLink, splitLink]),
})

您想要用于定位 WS connect/disconnect 事件的选项似乎是 connectionCallback(请参阅 WebSocketLink 选项的完整列表 here)。

查看 WebSocketLink 源的 lines 620-635,您可以看到提供的 connectionCallback 被调用用于 GQL_CONNECTION_ERRORGQL_CONNECTION_ACK 接收到的消息类型。因此,您应该能够使用此回调将这两个事件作为目标。

我还没有使用过 Apollo 的 WebSocketLink,所以我无法确认它是否会按预期完全工作。此外,在重新连接时获取所有丢失的聊天消息的行为可能需要您自己构建,因为它似乎不是默认重新连接行为的一部分(将取决于服务器实现;参见 Apollo Server docs)。相反,默认情况下,WebSocketLink 似乎会在重新连接时将所有未发送的消息转发到服务器。

我终于找到了解决办法。原来可以先声明一个SubscriptionClient然后把这个插入到WebSocketLink,而不是直接用WebSocketLink声明

使用 SubscriptionClient,您可以收听必要的事件,而使用 WebsocketLink 则不太可能(或非常有限)。

不幸的是,Apollo 文档中没有任何地方提到 SubscriptionClient 或处理连接问题的方法。

import { WebSocketLink } from '@apollo/client/link/ws'
import { SubscriptionClient } from 'subscriptions-transport-ws' // <- import this

const wsClient = new SubscriptionClient(config.WS_URL, {
  reconnect: true,
  connectionParams: {
    authToken: accessToken,
  },
})

const wsLink = new WebSocketLink(wsClient)

通过这样做,现在您可以使用 wsClient

监听连接事件
wsClient.onConnected(() => console.log("websocket connected!!"))
wsClient.onDisconnected(() => console.log("websocket disconnected!!"))
wsClient.onReconnected(() => console.log("websocket reconnected!!"))

还有更多活动可以收听。但是这些事件足以实现抓取未接聊天消息。

有了这些事件,在初始连接后,您可以存储 disconnectTimestamp 断开连接事件。当您收到 onReconnected 事件时,您可以简单地获取在 disconnectTimestamp

之后创建的聊天消息