23k star 的超火项目,网络请求优化却写的一塌糊涂?

3,854 阅读4分钟

前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心~

取消重复请求

取消重复请求是一个前端项目中很常见的网络请求优化手段,他主要是为了防止短时间内发送了多个一模一样的请求,导致性能的消耗~

23k star 的项目是怎么做的?

github 上有一个很火的项目,叫做 Vben-Admin,是一个非常出色的后台管理系统模板,但是个人觉得它的取消重复请求做的一塌糊涂(下面会说理由)!!!

由于项目中源代码比较多,我尽量简化了代码,给大家展示一下它是怎么去实现这个功能的

我先说一下它实现这个功能的思路:

  • 1、维护一个 Map:key 是 请求的 Method + Url,value 是这个请求的取消方法
  • 2、请求拦截器中:先清除掉 Map 中此请求 Method + Url 的存储,也就是取消掉前面的重复请求,然后再进行本次请求
  • 3、响应拦截器:清除掉本次请求的存储,确保不影响下一次的判断

简化后的代码如下

接着在页面中使用

假如我点击了三次,那么它会将我前面的两次取消掉,只让第三次请求成功,从而实现取消重复请求的功能~

但是这个方案缺陷真的很大,比如看下面的例子,我不止一个按钮调用了,我有两个按钮去调用这个接口

我先点击了按钮1,再点击按钮2,发现它把我按钮1的请求取消掉了,只请求了按钮2的请求,其实这是没错的,但是错就错在,它取消了按钮1的请求,但是连着按钮1点击事件接下来的代码都中断掉了!!!!

可以发现,控制台没有打印按钮1的结果,只打印了按钮2的结果!!!

这显然是不合理的,我们取消重复请求只是为了减少网络资源、性能的消耗,但是可不想因为这个优化,而影响了我们原本的逻辑~

其实上面的按钮1、按钮2,也可以类比为页面1、页面2,两个页面在短时间内发起了同一个请求,你直接去把页面1的后续逻辑都中断了,这不是一个好的方案!!!

并且其实不合理的地方还有:Method + Url当做 key,确实不太合理(本文暂且不关注这点)

自己思考怎么做~

想了一下,不能用上述的方案来做,缺陷太大了,自己想的方式就是不取消请求了!而是直接不发请求! 大概的思路如下:

  • 1、维护一个Map:key 是 请求的 Method + Url,value 第一次请求的 Promise
  • 2、第一次请求时,生成一个 Promise,存储在 Map 中
  • 3、第一次请求响应之后,修改 Promise 的状态,并把响应数据传给 Promise
  • 4、后续的重复请求以第一次请求的 Promise 为准,确保能复用数据,且不影响各自的后续逻辑

简化后的代码如下:

结果如下,按钮1、按钮2各自的后续逻辑会继续进行

且请求只会发出一次

第一个请求报错了咋办?

我这个方案是以第一个请求为主的,那么,如果第一个请求失败了,那后续的重复请求就爷跟着失败吗?显然是不对的~

第一个请求失败之后,我们必须让后续的请求再重新走一次流程才对,就像是一切都没发生过一样!

只需要在后续重复请求的错误回调中,重新执行请求即可,这样又能重新来过了!!!

可以看到,就算前面的失败了,后面的照样能自己发起请求进行自救

有完善的空间

以上只是我根据自己思路写出的一个粗略版本,如果大家有自己其他的顾虑,可以进行修改精进~

结语 & 加学习群 & 摸鱼群

我是林三心

  • 一个待过小型toG型外包公司、大型外包公司、小公司、潜力型创业公司、大公司的作死型前端选手;
  • 一个偏前端的全干工程师;
  • 一个不正经的掘金作者;
  • 一个逗比的B站up主;
  • 一个不帅的小红书博主;
  • 一个喜欢打铁的篮球菜鸟;
  • 一个喜欢历史的乏味少年;
  • 一个喜欢rap的五音不全弱鸡

如果你想一起学习前端,一起摸鱼,一起研究简历优化,一起研究面试进步,一起交流历史音乐篮球rap,可以来俺的摸鱼学习群哈哈,点这个,有7000多名前端小伙伴在等着一起学习哦 --> 摸鱼沸点