乐趣区

关于前端:记录第一次给开源项目提-PR

本文是深入浅出 ahooks 源码系列文章的第八篇,该系列已整顿成文档 - 地址。感觉还不错,给个 star 反对一下哈,Thanks。

本篇文章算是该系列的一个彩蛋篇,记录一下第一次给开源我的项目提 PR 的过程(之前如同也有过,不过那个十分小的一个改变),心愿可能帮忙更多的人参加到开源我的项目中来。

起因

在写了几篇对于 ahooks 的文章之后,收到了官网同学的私信。

这让我受宠若惊的同时也有点小兴奋和惶恐。

兴奋是,之前感觉参加开源是一件遥不可及的事件,当初仿佛我也可能去做了。当然也有公心,如果我的简历上有给开源我的项目做奉献的经验,那岂不是一个不错的加分项?

惶恐的是,我之前没有参加过开源我的项目,放心本人不能做好这件事。

依据大佬的倡议,我决定先从一些 issue 动手,也就是帮忙解决一下 issue。

明确问题 OR 需要

于是我抱着试试看的态度,看了一下官网的 issue,看到这么一条。issue 详情。

刚好我之前对 useRequest 源码做过一些剖析——如何应用插件化机制优雅的封装你的申请。于是我决定 fix 一下这个 issue。

这个 issue 的需要很简略,就是心愿轮询失败后,可能反对最大的轮询次数,如果失败的次数大于这个值,则进行轮询。

编码前筹备

首先,从 ahooks 官网 GitHub 中 folk 一份。这个操作我之前曾经做了。

第二步,基于 master 切换一个性能分支。如下:

git checkout -b fix/pollingSupportRetryCount

最初就是环境的一些初始化操作,不同的仓库不同,ahooks 如下:

yarn run init
yarn start

性能实现

咱们先来看下当初 useRequest 的轮询的实现,其原理次要是在一个申请完结的时候(不论胜利与失败),通过 setTimeout 进行从新申请,达到轮询的成果。

onFinally: () => {
  // 省略局部代码...
  // 通过 setTimeout 进行轮询
  timerRef.current = setTimeout(() => {fetchInstance.refresh();
  }, pollingInterval);
},

我的想法是,定义一个 options 参数,pollingErrorRetryCount,默认为 -1,代表没有限度。

另外定义一个变量,记录以后重试的次数:

const countRef = useRef<number>(0);

当开发者设置了 pollingErrorRetryCount,并且重试的数量大于该值,咱们就间接返回,不执行轮询的逻辑。

当胜利或者失败的时候,更新以后重试的次数:

onError: () => {countRef.current += 1;},
onSuccess: () => {countRef.current = 0;},

而后在申请完结的时候,判断重试的次数有没有达到了开发设置的次数,如果没有则执行重试操作。有则重置重试的次数,进行轮询。

onFinally: () => {
  if (
    pollingErrorRetryCount === -1 ||
    // When an error occurs, the request is not repeated after pollingErrorRetryCount retries
    (pollingErrorRetryCount !== -1 && countRef.current <= pollingErrorRetryCount)
  ) {
    // 疏忽局部代码
    timerRef.current = setTimeout(() => {fetchInstance.refresh();
    }, pollingInterval);
  } else {countRef.current = 0;}
},

测试用例

上述整体的革新并不艰难,然而我在写测试用例的时候,就开始踩坑了,因为我很少书写前端的测试用例,还是针对于 hooks 的测试用例。这里是我耗时最多的中央。

最终用例如下:

// 省略局部代码...
// if request error and set pollingErrorRetryCount
// and the number of consecutive failures exceeds pollingErrorRetryCount, polling stops
let hook2;
let errorCallback;
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();
});
await hook2.waitForNextUpdate();
expect(hook2.result.current.loading).toEqual(false);
expect(errorCallback).toHaveBeenCalledTimes(1);

act(() => {jest.runAllTimers();
});
await hook2.waitForNextUpdate();
expect(errorCallback).toHaveBeenCalledTimes(2);

act(() => {jest.runAllTimers();
});
await hook2.waitForNextUpdate();
expect(errorCallback).toHaveBeenCalledTimes(3);

act(() => {jest.runAllTimers();
});
await hook2.waitForNextUpdate();
expect(errorCallback).toHaveBeenCalledTimes(4);

act(() => {jest.runAllTimers();
});
expect(errorCallback).toHaveBeenCalledTimes(4);

act(() => {hook2.result.current.run();
});
act(() => {jest.runAllTimers();
});
await hook2.waitForNextUpdate();
expect(errorCallback).toHaveBeenCalledTimes(5);

hook2.unmount();
// 省略局部代码...

大抵解释下该测试用例的逻辑,我设置了重试三次,谬误之后,运行了三次,errorCallback 就会被调用了 4 次(包含谬误那次)。在第五次执行的时候,就不会执行 errorCallback,也就还是 4 次。而后咱们手动 run 一次申请,期待 errorCallback 应该执行 5 次。

这里踩了一个坑,就是第五次申请的时候,我之前是会写一个期待定时器执行的操作,但实际上这里它是不会执行定时器的,导致始终报错,在这里折腾了很久。起初删除了上面的代码才执行胜利。

act(() => {jest.runAllTimers();
});
- await hook2.waitForNextUpdate();
expect(errorCallback).toHaveBeenCalledTimes(4);

文档以及 Demo 补充

毕竟加了一个新的 API 参数,须要在文档中注明,而且中英文文档都须要补充,还加上了一个 Demo 示例。

提 PR

上述都实现之后,就能够提交你的代码了,提交完,去到在你 folk 过去的我的项目中,能够看到这个。

咱们须要点击图中框起来的「Compare & pull request」,之后就会呈现如下图

默认会帮咱们选好分支的,咱们只须要欠缺其中的信息,还有咱们之前提交的 message 也能够批改。最好能够用英文来解释,本次提交的内容。

最初点击提交之后就好了。

还有一个提 PR 的入口,如下所示:

最初期待官网 CR 就能够了(下面的实现其实局部是 CR 后改的)。目前该 PR 曾经被合入到 master。

总结思考

给开源我的项目提 PR 操作过程 不是一件很简单的事件,重点在于需要的批改。往往须要思考到多种边界场景,这个时候,咱们就须要前端的单元测试来帮忙咱们笼罩全面的场景。

另外,对于一些还没有参加开源我的项目教训的同学来讲,我感觉相似 ahooks 这种工具库是一个不错的抉择:

  • 它的模块划分更加清晰,你改了一个模块的性能,影响面能够更好的预估。对新人比拟敌对。
  • 逻辑绝对简略,其实你会发现很多代码说不定在你们的业务我的项目中的 utils/hooks 文件夹中就有。
  • 社区比拟沉闷,维护者可能较快的响应。

心愿对大家有所帮忙。

退出移动版