如何使用插件化机制优雅地封装你的请求Hook

网站建设4年前发布
227 0 0

本文是深入浅出 ahooks 源码系列文章的第二篇,这个系列的目标主要有以下几点:,注:本系列对 ahooks 的源码解析是基于 ​​v3.3.13​​。自己 folk 了一份源码,主要是对源码做了一些解读,可见 详情[1]。,系列文章:,本文来讲下 ahooks 的核心 hook —— useRequest。,根据官方文档的介绍,useRequest 是一个强大的异步数据管理的 Hooks,React 项目中的网络请求场景使用 useRequest 就够了。,useRequest 通过插件式组织代码,核心代码极其简单,并且可以很方便的扩展出更高级的功能。目前已有能力包括:,这里可以看到 useRequest 的功能是非常强大的,如果让你来实现,你会如何实现?也可以从介绍中看到官方的答案——插件化机制。,如上图所示,我把整个 useRequest 分成了几个模块。,先从入口文件开始,packages/hooks/src/useRequest/src/useRequest.ts。,这里第一(service 请求实例)第二个参数(配置选项),我们比较熟悉,第三个参数文档中没有提及,其实就是插件列表,用户可以自定义插件拓展功能。,可以看到返回了 useRequestImplement 方法。主要是对 Fetch 类进行实例化。,实例化的时候,传参依次为请求实例,options 选项,父组件的更新函数,初始状态值。,这里需要非常留意的一点是最后一行,它执行了所有的 plugins 插件,传入的是 fetchInstance 实例以及 options 选项,返回的结果赋值给 fetchInstance 实例的 pluginImpls。,另外这个文件做的就是将结果返回给开发者了,这点不细说。,接下来最核心的源码部分 —— Fetch 类。其代码不多,算是非常精简,先简化一下:,在 constructor 中,主要是进行了数据的初始化。其中维护的数据主要包含一下几个重要的数据以及通过 setState 方法设置数据,设置完成通过 subscribe 调用通知 useRequestImplement 组件重新渲染,从而获取最新值。,上文有提到所有的插件运行的结果都赋值给 pluginImpls。它的类型定义如下:,除了最后一个 onMutate 之外,可以看到返回的方法都是在一个请求的生命周期中的。一个请求从开始到结束,如下图所示:,如果你比较仔细,你会发现基本所有的插件功能都是在一个请求的一个或者多个阶段中实现的,也就是说我们只需要在请求的相应阶段,执行我们的插件的逻辑,就能完成我们插件的功能。,执行特定阶段插件方法的函数为 runPluginHandler,其 event 入参就是上面 PluginReturn key 值。,通过这样的方式,Fetch 类的代码会变得非常的精简,只需要完成整体流程的功能,所有额外的功能(比如重试、轮询等等)都交给插件去实现。这么做的优点:,可以看到 runAsync 是运行请求的最核心方法,其他的方法比如 run/refresh/refreshAsync 最终都是调用该方法。,并且该方法中就可以看到整体请求的生命周期的处理。这跟上面插件返回的方法设计是保持一致的。,处理请求前的状态,并执行 Plugins 返回的 onBefore 方法,并根据返回值执行相应的逻辑。比如,useCachePlugin 如果还存于新鲜时间内,则不用请求,返回 returnNow,这样就会直接返回缓存的数据。,这个阶段只有 useCachePlugin 执行了 onRequest 方法,执行后返回 service Promise(有可能是缓存的结果),从而达到缓存 Promise 的效果。,useCachePlugin 返回的 onRequest 方法:,刚刚在请求开始前定义了 currentCount 变量,其实为了 cancel 请求。,在请求过程中,开发者可以调用 Fetch 的 cancel 方法:,这个时候,currentCount !== this.count,就会返回空数据。,这部分也就比较简单了,通过 try...catch...最后成功,就直接在 try 末尾加上 onSuccess 的逻辑,失败在 catch 末尾加上 onError 的逻辑,两者都加上 onFinally 的逻辑。,useRequest 是 ahooks 最核心的功能之一,它的功能非常丰富,但核心代码(Fetch 类)相对简单,这得益于它的插件化机制,把特定功能交给特定的插件去实现,自己只负责主流程的设计,并暴露相应的执行时机即可。,这对于我们平时的组件/hook 封装很有帮助,我们对一个复杂功能的抽象,可以尽可能保证对外接口简单。内部实现需要遵循单一职责的原则,通过类似插件化的机制,细化拆分组件,从而提升组件可维护性、可测试性。,[1]详情: https://github.com/GpingFeng/hooks。,[2]大家都能看得懂的源码(一)ahooks 整体架构篇: https://juejin.cn/post/7105396478268407815。,[3]软件设计之Deep Module(深模块): https://www.cnblogs.com/hhelibeb/p/10708951.html。,[4]精读 ahooks useRequest 源码: https://juejin.cn/post/7042489413292523534#heading-4。

© 版权声明

相关文章