ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Apollo Client GraphQLWsLink 完整指南:基于 graphql-ws 在 WebSocket 上执行订阅操作

Apollo Client GraphQLWsLink 完整指南:基于 graphql-ws 在 WebSocket 上执行订阅操作 Apollo Client GraphQLWsLink 完整指南基于 graphql-ws 在 WebSocket 上执行订阅操作【免费下载链接】apollo-clientThe industry-leading GraphQL client for TypeScript, JavaScript, React, Vue, Angular, and more. Apollo Client delivers powerful caching, intuitive APIs, and comprehensive developer tools to accelerate your app development.项目地址: https://gitcode.com/gh_mirrors/ap/apollo-clientGraphQLWsLink是 Apollo Client 提供的终止型terminating链接Link它借助graphql-ws库通过 WebSocket 连接向 GraphQL 服务器发送操作尤其是订阅操作。本文以.api-reports/api-report-link_subscriptions.api.md中公开的 API 契约为骨架结合src/link/subscriptions/index.ts的源码实现、官方订阅文档与测试用例系统讲解其安装、初始化、底层请求构造、错误处理、与 HTTP 链路拆分组合的实战接入以及它与已废弃的WebSocketLink的差异帮助你掌握在真实项目中正确接入实时订阅的能力。GraphQLWsLink 的公开 API 契约该类的公开 API 由 API Extractor 生成并固化在 .api-reports/api-report-link_subscriptions.api.md 中属于apollo/client/link/subscriptions入口下的public导出import { ApolloLink } from apollo/client/link; import type { Client } from graphql-ws; import { Observable } from rxjs; export class GraphQLWsLink extends ApolloLink { constructor(client: Client); readonly client: Client; request(operation: ApolloLink.Operation): ObservableApolloLink.Result; }从这份契约可以提炼出三个关键事实构造参数唯一构造函数只接受一个Client实例即graphql-ws库中通过createClient()创建出来的 WebSocket 客户端公开只读成员client底层graphql-ws客户端对外暴露便于在特殊场景下直接访问request返回 rxjsObservable与 Apollo Link 体系保持一致——每个链接的request方法接收ApolloLink.Operation返回可被上游链接和QueryManager消费的ObservableApolloLink.Result。安装与初始化官方文档 docs/source/api/link/apollo-link-subscriptions.mdx 明确指出GraphQLWsLink本身并不内置 WebSocket 通信能力它依赖graphql-ws库需要单独安装npm install graphql-ws安装完成后在与初始化ApolloClient相同的项目文件中创建实例import { GraphQLWsLink } from apollo/client/link/subscriptions; import { createClient } from graphql-ws; const wsLink new GraphQLWsLink( createClient({ url: ws://localhost:4000/subscriptions, }) );其中url是必填项指向 GraphQL 服务器的订阅专用 WebSocket 端点通常以ws://或wss://开头详见 docs/source/data/subscriptions.mdx。createClient还支持更多ClientOptions如连接参数、重连策略、事件回调等这些选项由graphql-ws库本身解析GraphQLWsLink不做二次加工只负责把操作转发给该客户端。底层实现原理request 方法源码解析整个链接的核心逻辑集中在 src/link/subscriptions/index.ts 中实现非常精简export class GraphQLWsLink extends ApolloLink { constructor(public readonly client: Client) { super(); } public request( operation: ApolloLink.Operation ): ObservableApolloLink.Result { return new Observable((observer) { const { query, variables, operationName, extensions } operation; return this.client.subscribeApolloLink.Result( { variables, operationName, extensions, query: print(query) }, { next: observer.next.bind(observer), complete: observer.complete.bind(observer), error: (err) { /* ... */ }, } satisfies SinkFormattedExecutionResult as any ); }); } }这里有四个值得注意的细节操作载荷payload只透传四个字段query、variables、operationName、extensions。测试用例sends only known keys to the GraphQLWsLink对应 src/link/subscriptions/tests/graphqlWsLink.ts专门验证了这一点——它断言subscribe收到的 payload 的 key 集合恰好等于这四项防止其他内部字段泄漏到 WebSocket 连接上print(query)查询文档在发送前经过apollo/client/utilities导出的print函数序列化为 GraphQL 标准字符串而不是直接发送DocumentNode对象这是graphql-ws协议对 payload 的格式要求rxjs Observable 桥接GraphQLWsLink把graphql-ws基于回调的 Sink 接口next/complete/error桥接为 rxjs 的Observer从而无缝融入 Apollo Link 的 Observable 链路类型断言satisfies SinkFormattedExecutionResult as any源码注释说明这是为了绕过graphql-ws中错误的类型定义它误将订阅类型声明为SinkExecutionResult对运行时行为没有影响。三种操作类型均支持测试文件 src/link/subscriptions/tests/graphqlWsLink.ts 中的多个用例证明GraphQLWsLink对 query、mutation、subscription 三类操作一视同仁地调用client.subscribequery调用一次subscribe并收到单个结果后completemutation行为与 query 一致subscriptionnext被多次调用每次服务端推送一条数据最后complete。因此它既可以作为纯订阅链路也可以单独承载全部操作类型只是文档并不推荐后者原因见下文“与 HTTP 拆分组合”一节。错误处理机制GraphQLWsLink的error回调实现了分级错误归一化逻辑同样在 src/link/subscriptions/index.ts 中error: (err) { if (err instanceof Error) { return observer.error(err); } const likeClose isLikeCloseEvent(err); if (likeClose || isLikeErrorEvent(err)) { return observer.error( new Error( Socket closed${likeClose ? with event ${err.code} : }${ likeClose ? ${err.reason} : } ) ); } return observer.error( new CombinedGraphQLErrors({ errors: Array.isArray(err) ? err : [err], }) ); }对应四种典型场景均有测试用例覆盖错误来源判定方式最终抛出的错误普通Errorerr instanceof Error原样转发如new Error(an error occurred)WebSocketCloseEvent如 code 1006 异常关闭isLikeCloseEvent对象含code与reason字段Error(Socket closed with event 1006 abnormally closed)WebSocket 通用Event网络断开readyState CLOSEDisLikeErrorEventError(Socket closed)GraphQLError[]错误数组兜底分支CombinedGraphQLErrors实例最后一种场景涉及 Apollo Client 的CombinedGraphQLErrors错误类型实现在 src/errors/CombinedGraphQLErrors.ts它把服务端返回的多个 GraphQL 错误合并为一个Error子类并保留errors、data、extensions等原始响应字段方便上层通过CombinedGraphQLErrors.is(error)做类型收窄后逐个读取error.errors。测试用例with CombinedGraphQLErrors on subscription error via GraphQLError[]验证了sink.error([new GraphQLError(Foo bar.)])会被转换为new CombinedGraphQLErrors({ errors: [{ message: Foo bar. }] })。需要说明的是以上错误归一化发生在链接层而到useSubscription或client.subscribe()层面时Apollo Client 的订阅错误传递遵循另一套规则错误通过result.error传递、error回调不触发具体可参考 docs/source/data/subscriptions.mdx 中的说明。实战接入与 HTTP 链路拆分组合尽管GraphQLWsLink能执行所有操作类型官方文档明确建议查询与变更继续走 HTTP只有订阅走 WebSocket原因是 HTTP 对无状态、非长连接的请求更高效且不必常驻连接详见 docs/source/data/subscriptions.mdx。为此 Apollo Client 提供了ApolloLink.split在 src/link/core/split.ts 中作为废弃 API 导出推荐直接使用ApolloLink.split它接收三个参数一个对每次操作求值的判定函数、判定为真时使用的链接、判定为假时使用的链接import { OperationTypeNode } from graphql; import { ApolloLink, HttpLink } from apollo/client; import { GraphQLWsLink } from apollo/client/link/subscriptions; import { createClient } from graphql-ws; const httpLink new HttpLink({ uri: http://localhost:4000/graphql, }); const wsLink new GraphQLWsLink( createClient({ url: ws://localhost:4000/subscriptions, }) ); const splitLink ApolloLink.split( ({ operationType }) { return operationType OperationTypeNode.SUBSCRIPTION; }, wsLink, httpLink );随后将拆分后的链路交给ApolloClientimport { ApolloClient, InMemoryCache } from apollo/client; const client new ApolloClient({ link: splitLink, cache: new InMemoryCache(), });可选WebSocket 连接认证订阅端经常需要鉴权可以通过graphql-ws的connectionParams选项在连接建立时向服务器传递凭证详见 docs/source/data/subscriptions.mdxconst wsLink new GraphQLWsLink( createClient({ url: ws://localhost:4000/subscriptions, connectionParams: { authToken: user.authToken, }, }) );GraphQLWsLink会把该对象原样透传给服务器服务器在连接ConnectionInit阶段即可基于其中的内容完成认证或其他连接级处理。注意connectionParams与旧版库不同它位于createClient选项的顶层而非嵌套在某个options对象里。连接重试策略对于失败连接的自动重试docs/source/api/link/apollo-link-subscriptions.mdx 给出了两条路线首选在graphql-ws客户端层按官方 recipes 配置重连逻辑因为该层面能拿到连接失败的具体原因如服务端拒绝、握手失败等诊断信息最完整备选在链路层使用 RetryLink 泛化处理——当终止链接上报失败时RetryLink会把操作重新发送给链路实现通用的重试语义。这两条路线可以组合使用具体取舍取决于你希望重试逻辑关注的是“连接层”还是“操作层”的失败。与已废弃的 WebSocketLink 对比apollo/client还保留了基于subscriptions-transport-ws库的WebSocketLink入口为apollo/client/link/ws。其 API 报告见 .api-reports/api-report-link_ws.api.md实现见 src/link/ws/index.ts。两者的关键差异如下维度GraphQLWsLinkWebSocketLink底层库graphql-ws积极维护subscriptions-transport-ws已停止维护标记deprecatedWebSocket 子协议graphql-transport-ws名为graphql-ws的旧子协议构造参数单个Client实例Configuration对象或SubscriptionClient实例实例化时代码new GraphQLWsLink(createClient({ url }))new WebSocketLink(new SubscriptionClient(url, { connectionParams }))开发环境提示无构造时通过invariant.warn输出弃用警告建议迁移到GraphQLWsLink从源码看WebSocketLink在开发环境构造时会输出一段明确的弃用警告并将在未来主版本中被移除src/link/ws/index.ts。官方订阅文档的 “The older subscriptions-transport-ws library” 一节给出了从旧库迁移的三步替换法依赖改为subscriptions-transport-ws、createClient改为SubscriptionClient、GraphQLWsLink改为WebSocketLink。但值得注意的是两个库使用的 WebSocket 子协议互不兼容必须与服务端实际使用的协议一致否则订阅无法建立。相关阅读官方链接 API 文档docs/source/api/link/apollo-link-subscriptions.mdx订阅完整指南协议选择、useSubscription、subscribeToMore、错误处理docs/source/data/subscriptions.mdx链接体系与终止链接概念docs/source/api/link/introduction.mdx测试用例query/mutation/subscription 三类操作及四类错误场景src/link/subscriptions/tests/graphqlWsLink.ts【免费下载链接】apollo-clientThe industry-leading GraphQL client for TypeScript, JavaScript, React, Vue, Angular, and more. Apollo Client delivers powerful caching, intuitive APIs, and comprehensive developer tools to accelerate your app development.项目地址: https://gitcode.com/gh_mirrors/ap/apollo-client创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表