本文是浅显易懂的ahooks源码系列文章的第八篇。本系列已整理成文档地址。觉得还不错,给个star支持一下,谢谢。这篇文章可以看作是这个系列的彩蛋文章。记录下第一次向开源项目提交PR的过程(以前好像有过,不过那是一个很小的变化),希望能帮助更多人参与到开源项目中。来。起因是在写了几篇关于ahooks的文章后,收到了一位正式同学的私信。这让我受宠若惊,同时又有些兴奋和害怕。兴奋的是,以前参与开源感觉遥不可及,现在看来自己可以做到了。当然,也有私心。如果我的简历有为开源项目做贡献的经历,那不是一个很好的加分项吗?忐忑的是之前没有参与过开源项目,担心自己做不好这块。根据老大的建议,我决定先从一些问题入手,也就是帮助解决问题。弄清楚问题OR需求,看了一下官方issue,抱着试一试的态度看到了这个。问题细节。刚才对useRequest的源码做了一些分析——如何使用插件机制来优雅的封装你的请求。所以我决定解决这个问题。这个问题的要求很简单。希望在轮询失败后,能够支持最大轮询次数。如果失败次数大于此值,轮询将停止。编码前的准备首先,从ahooks官方GitHub上抄了一份民间的。我以前做过这个。第二步,切换一个基于master的功能分支。如下:gitcheckout-bfix/pollingSupportRetryCount最后是环境的一些初始化操作。不同的仓库不同,ahooks如下:yarnruninityarnstart函数实现。我们先看useRequest轮询的实现。原理主要是在一个请求结束时(不管成功还是失败),通过setTimeout重新请求,达到轮询的效果。onFinally:()=>{//省略部分代码...//通过setTimeouttimerRef.current=setTimeout(()=>{fetchInstance.refresh();},pollingInterval);},我的想法是,定义一个options参数,pollingErrorRetryCount,默认为-1,表示没有限制。另外定义一个变量记录当前重试次数:constcountRef=useRef(0);当开发者设置了pollingErrorRetryCount,重试次数大于这个值,我们就直接返回,不执行轮询逻辑。成功或失败时,更新当前重试次数:onError:()=>{countRef.current+=1;},onSuccess:()=>{countRef.current=0;},然后在最后request时判断重试次数是否达到开发设置的次数,没有则执行重试操作。如果有,重新设置重试次数并停止轮询。onFinally:()=>{if(pollingErrorRetryCount===-1||//发生错误时,pollingErrorRetryCount重试后不再重复请求(pollingErrorRetryCount!==-1&&countRef.current<=pollingErrorRetryCount)){//忽略部分代码timerRef.current=setTimeout(()=>{fetchInstance.refresh();},pollingInterval);}else{countRef.current=0;}}、测试用例上面的整体改造并不难,但是我在写测试用例的时候,开始踩坑了,因为我很少写前端测试用例,或者hooks的测试用例。这是我花时间最多的地方。最终使用示例如下://节省部分代码...//如果请求错误并设置pollingErrorRetryCount//并且连续失败的次数超过pollingErrorRetryCount,轮询stoplethook2;leterrorCallback;act(()=>{errorCallback=jest.fn();hook2=setUp(()=>request(0),{pollingErrorRetryCount:3,pollingInterval:100,pollingWhenHidden:true,onError:errorCallback,});});expect(hook2.result.current.loading)。toEqual(true);expect(errorCallback).toHaveBeenCalledTimes(0);act(()=>{jest.runAllTimers();});awaithook2.waitForNextUpdate();expect(hook2.result.current.loading).toEqual(false);期望(errorCallback).toHaveBeenCalledTimes(1);act(()=>{jest.runAllTimers();});awaithook2.waitForNextUpdate();期望(errorCallback).toHaveBeenCalledTimes(2);act(()=>{jest.runAllTimers();});awaithook2.waitForNextUpdate();expect(errorCallback).toHaveBeenCalledTimes(3);act(()=>{jest.runAllTimers();});awaithook2.waitForNextUpdate();expect(errorCallback).toHaveBeenCalledTimes(4);act(()=>{jest.runAllTimers();});expect(errorCallback).toHaveBeenCalledTimes(4);act(()=>{hook2.result.current.run();});act(()=>{jest.runAllTimers();});awaithook2.waitForNextUpdate();expect(errorCallback).toHaveBeenCalledTimes(5);hook2.unmount();//省略部分代码...大致说明一下测试用例的逻辑,我设置了重试3次,报错后,运行3次后,执行到第5次时会调用4次errorCallback(包括报错)次,不会执行errorCallback,还是4次。然后我们手动运行一个请求,期望errorCallback应该执行5次。我这里踩了一个坑,就是我在进行第五次请求的时候,我会写一个等待定时器执行的操作,但是实际上这里并不会执行定时器,导致一直报错,也在这里折腾了好久。后来删掉下面代码执行成功。act(()=>{jest.runAllTimers();});-awaithook2.waitForNextUpdate();期望(errorCallback).toHaveBeenCalledTimes(4);文档和Demo补充毕竟新增了一个API参数,需要在文档Indicated中添加,同时需要补充中英文文档,同时添加一个Demo示例。完成上述所有PR后,您就可以提交代码了。提交后,从你的folk转到项目,你可以看到这个。我们需要点击图中框出的“Compare&pullrequest”,然后会出现下图,默认会帮助我们选择分支。我们只需要完善里面的信息,之前提交的消息也可以修改。最好是英文的,能说明本次投稿的内容。最后点击提交即可。还有一个提交PR的入口,如下图:最后,就等官方CR了(上面的实现其实是CR之后的部分修改)。目前PR已经合并到master。综上所述,向开源项目提交PR并不是一个非常复杂的过程。重点是需求的修改。通常需要考虑各种边界场景。这时候就需要前端单元测试来帮助我们覆盖全面的场景。另外,对于一些还没有参与过开源项目经验的同学,我觉得像ahooks这样的工具库是一个不错的选择:它的模块划分比较清晰,如果改变一个模块的功能,影响面可以更好的估计。对新人友好。逻辑相对简单。事实上,你会发现在你的业务项目中的utils/hooks文件夹中可能存在很多代码。社区更加活跃,维护者可以更快地响应。我希望能有所帮助。