` 生命周期解析(v20 API 参考))
前端开发工具【免费下载链接】relayRelay is a JavaScript framework for building>项目地址https://gitcode.com/gh_mirrors/relay29/relay点击查看免费下载Disposable是 Relay 中最基础也最关键的一个接口约定任何需要被显式释放的资源都通过一个带dispose()方法的对象向外暴露。在 Relay 20 的 API 参考中Disposable被commitMutation、requestSubscription、store 的retain/subscribe等大量 API 作为统一返回值理解它就能读懂 Relay 中订阅如何取消、乐观更新如何回滚、查询结果如何被保留等一整套生命周期管理机制。读完本文你将掌握Disposable的精确类型定义、它在运行时与 Store 中的底层实现、以及如何在 React hooks 和命令式 API 中正确地释放资源。接口定义唯一约定是dispose根据 Disposable.md 的原始定义Disposable接口极其精简InterfaceDisposableAn object with the following key:dispose:() void. Disposes of the resource.即一个包含dispose键的对象dispose是一个无参数、无返回值的函数() void调用它即释放该资源。在 glossary.md 的Disposable词条中这一约定被进一步解释为Any object which contains a.disposemethod which takes no parameters and provides no return value. Many objects in Relay (such query references and entrypoint references) and the return value of many methods (such as calls to.subscribeor.retain) are disposables.也就是说Relay 中大量对象本身就是 Disposable例如 query reference、entrypoint reference而许多方法的返回值也是 Disposable例如调用.subscribe或.retain的返回结果。dispose不接收参数、不返回任何值这是它唯一的形状约束——具体释放了什么语义由返回它的 API 决定。源码中的类型定义TypeScript 与 Flow 双实现Disposable接口的实际类型定义位于 packages/relay-runtime/util/RelayRuntimeTypes.d.ts/** * Represents any resource that must be explicitly disposed of. The most common * use-case is as a return value for subscriptions, where calling dispose() * would cancel the subscription. */ export interface Disposable { dispose: DisposeFn; }同文件第 31 行给出了DisposeFn的精确定义export type DisposeFn () void;文件顶部的注释点明了它在 Relay 中最典型的应用场景作为订阅subscription的返回值调用dispose()即取消订阅。由于 Relay 的运行时是一份代码、双类型系统对应的 Flow 类型定义写在 packages/relay-runtime/util/RelayRuntimeTypes.jsexport type Disposable interface {dispose(): void};可以看到无论 TypeScript 还是 Flow 视角契约都只有一条对象上存在一个dispose()方法。哪些 Relay API 会返回Disposable围绕这个统一约定Relay 运行时中几乎所有命令式资源的入口都以Disposable作为返回值。下面按功能分组说明并给出源码依据。1. 变更MutationcommitMutation/applyOptimisticMutationcommitMutation 命令式执行一个变更返回一个Disposable其dispose语义在该文档中有明确描述若在请求完成前调用会取消并回滚任何乐观更新阻止onComplete与onError回调执行不一定会取消底层网络请求并触发onUnsubscribe回调若在初始请求完成后调用不做任何事。其实现位于 packages/relay-runtime/mutations/commitMutation.js内部将environment.executeMutation(...)返回的 Observable 订阅起来最后一行直接返回return {dispose: subscription.unsubscribe};也就是说commitMutation返回的 Disposable 的dispose就是底层订阅的unsubscribe——调用它即退订该 mutation 请求对应的 Observable从而中止后续回调与乐观更新。类似的packages/relay-runtime/mutations/applyOptimisticMutation.js 的签名同样返回Disposable用于只应用乐观更新而不真正发起网络请求的场景。2. 订阅SubscriptionrequestSubscriptionrequestSubscription 是命令式建立 GraphQL 订阅的入口其返回值是一个会清除订阅的 Disposable。对应实现见 packages/relay-runtime/subscription/requestSubscription.js同样是对environment.executeSubscription(...)返回的 Observable 进行订阅后返回return { dispose: sub.unsubscribe, };这与类型定义文件注释中subscription 场景下dispose()即取消订阅的描述完全对应。3. 环境Environment乐观更新applyUpdate/applyMutation在 packages/relay-runtime/store/RelayModernEnvironment.js 中applyUpdate(optimisticUpdate)返回applyUpdate(optimisticUpdate: OptimisticUpdateFunction): Disposable { const dispose () { this._scheduleUpdates(() { this._publishQueue.revertUpdate(optimisticUpdate); this._publishQueue.run(); }); }; ... return {dispose}; }可见这里的dispose语义是将已应用的乐观更新从发布队列publish queue中回滚并重新运行队列。而applyMutation同文件 L232-L245则返回{dispose: () subscription.unsubscribe()}。4. Storeretain/subscribe/holdGC在 runtime-architecture.md 中可以看到 Store 接口层面的两个 Disposable 约定subscribe(snapshot, callback): Disposable订阅某个 selector 结果的变化回调在数据发布时触发retain(selector): Disposable确保满足该 selector 所需的记录保留在内存中直到返回的引用被 dispose记录才可能被垃圾回收。Store 的具体实现位于 packages/relay-runtime/store/RelayModernStore.jsretain()返回的 Disposable 展示了一个重要的实现细节——幂等性只释放一次retain(operation: OperationDescriptor): Disposable { const id operation.request.identifier; let disposed false; const dispose () { // Ensure each retain can only dispose once if (disposed) { return; } disposed true; ... rootEntry.refCount--; if (rootEntry.refCount 0) { ... } }; ... }dispose内部通过disposed标志保证同一 Disposable 只能生效一次并通过引用计数refCount管理记录的可回收性只有引用计数归零后记录才进入可释放状态。这正是retain 引用不被释放、记录就不会被 GC 回收这一文档语义的落地实现。此外RelayModernStore的subscribe()L700-L705返回this._storeSubscriptions.subscribe(...)的 DisposableholdGC()L707-L723也返回{dispose}来递减 GC 持有计数。在 RelayModernStore-test.js 的测试用例中可以看到const {dispose: disposeA} writeAndRetainNode(a)这类通过解构dispose来释放 retain 引用的典型测试写法。在 React hooks 中如何消费DisposableRelay 的 hooks 是把Disposable与 React 生命周期桥接起来的最佳示例。useSubscription用 useEffect 自动释放useSubscription 的实现见 packages/react-relay/relay-hooks/useSubscription.jsuseEffect(() { // $FlowFixMe const {dispose} actualRequestSubscription(environment, config); return dispose; }, [environment, config, actualRequestSubscription]);它解构出返回 Disposable 的dispose并直接把它作为useEffect的清理函数返回。这样 React 会在 effect 重跑或组件卸载时自动调用dispose()订阅随之被取消无需手动管理。useSubscription还支持传入自定义的requestSubscriptionFn类型为(IEnvironment, GraphQLSubscriptionConfig) Disposable见同文件 L24-L27。useMutation用 Set 跟踪在途变更useMutation 返回的commit函数签名是(UseMutationConfig) Disposable见 packages/react-relay/relay-hooks/useMutation.js。实现中用一个inFlightMutationsRefnew SetDisposable()L79跟踪所有在途 mutation 的 Disposable并在onCompleted/onError/onUnsubscribe回调中调用cleanup(disposable)将其从集合移除、更新是否有变更在途的布尔状态L107-L133。调用者拿到 Disposable 后也可以手动dispose()取消尚未完成的变更。使用Disposable的实践要点综合上述文档与源码可以把Disposable的使用要点归纳为以下几点形状固定dispose是() void无参数、无返回值。const {dispose} someDisposable; dispose();是唯一标准的释放方式。语义由返回方定义同一个Disposable类型在commitMutation里代表取消乐观更新并中止回调在requestSubscription里代表清除订阅在retain里代表释放记录引用、使其可被 GC——具体含义取决于返回它的 API查阅对应 API 文档即可。注意幂等性Store 的retain返回的 Disposable 内部做了只释放一次的保护但其他 API如commitMutation在请求完成前后调用dispose的行为是不同的完成前取消、完成后空操作因此释放时机仍应遵循各 API 文档的说明。善用 React 生命周期在 hooks 中优先像useSubscription那样把dispose作为useEffect的清理函数返回让框架自动完成释放命令式场景如非组件代码则需要确保资源不再需要时主动调用dispose()避免乐观更新残留、订阅泄漏或记录长期驻留内存。Disposable虽然只是一个只含一个方法的极简接口却是贯穿 Relay 变更、订阅、Store 保留机制和 React hooks 的通用资源句柄。掌握了它的约定与各 API 的具体释放语义就能准确控制 Relay 应用中每一个异步资源的生命周期。赞分享前端开发工具【免费下载链接】relayRelay is a JavaScript framework for building>项目地址https://gitcode.com/gh_mirrors/relay29/relay点击查看免费下载相关推荐Relay Disposable 接口解析dispose() 契约与资源生命周期管理Relay Disposable 接口解析dispose 契约与资源生命周期管理 Disposable 是 Relay 运行时中定义资源释放契约的通用接口任前端开发工具Relay 中的 Disposable 接口理解 dispose() 契约与资源释放最佳实践Relay 中的 Disposable 接口理解 dispose 契约与资源释放最佳实践 Relay 的运行时与 React Hooks 体系中几乎所有会“前端开发工具Relay 中的 Disposable 接口理解 dispose() 的资源释放与订阅取消机制Relay 中的 Disposable 接口理解 dispose 的资源释放与订阅取消机制 Disposable 是 Relay 运行时中一个基础而关键的类型前端开发工具上一篇免费开源工具caj2pdf终极指南3步轻松转换CAJ学术文献为PDF下一篇KMS_VL_ALL_AIOWindows与Office激活的终极解决方案深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考