失败的axios防抖

前言

事情的起因是这样的,上周六的下午,正当我舒服的躺床上咸鱼的时候,产品在钉钉上发了条消息:甲方有个按钮操作操作不了了!

由于是周六加上功能上线前都有过测试,大概率是后台数据问题,于是先假装没看到,打算先观望会儿。果然不出几分钟,后台小姐姐直接回复:好了。

产品问原因,后台回复:甲方1操作连续发送了两次请求,导致把甲方2的操作也执行掉了(我们有个任务确定功能,需要两个人都确定才可以执行),同时发过来一张图:

上面的几条数据,基本都是在同时完成的,甚至有时分秒毫秒都完全一致的数据。

小姐姐的意思是,甲方网卡还是什么原因,导致前端发送了两次请求。两次请求虽然不可能同时发送,但是因为请求速度原因,慢的可以追上快的(龟兔赛跑😳),就产生了这种数据情况。

既然小姐姐这么说了,那就得改不是,于是,开始了入坑之路。

寻找方法

当初一开始开发的时候,思考的不全面(没想到甲方的网络这么差!),没有在每一次请求的时候加上加载loading和限制重复请求,导致甲方在等待的过程中,点击了按钮没反应,于是又点了一遍😨

但因为项目已经完成了,再去每个页面查漏补缺添加loading,耗费的时间有点多,并且在这个方法也不能一劳永逸,万一以后谁开发的时候忘记写了还得查一次(这就是需要开发规范的重要意义!)

还好,当初至少还封装过了axios请求,虽然不能在请求时候单纯的加上loading,但是,我可以做拦截重复请求呀!😊 —— 大坑

使用lodash debounce的入坑史

由于之前从没搞过防抖,找大佬问下了主要技术,就屁颠屁颠的去看lodash的文档,好像不太会……上百度,虽然没有我需要的axios搭配debounce的配方,凭着我的机智小脑袋,还是在axios里成功应用,由此引发了一系列的bug😭(此时有看到其他的方法解决,但是满心以为当前方法更好的我……)

坑1

export default function(config){

return _.debounce(function () {

axios(config)

}, 500)

}

首次尝试这样使用debounce,没想到报错this.$http(...).then is not a function,一脸懵的各种百度,各种求助。

坑2

debounce里的方法一直都执行不到,以为是异步的问题,改代码如下:

export default function(config){

return new Promise((resolve, reject) => {

_.debounce(function () {

axios(config).then(res => {

resolve(res.data)

}).catch(error => {

reject()

console.error(error)

})

}, 500)

})

}

报错没了,但是还是没有执行到debounce里的方法,导致没有发送任何请求。再次懵😵。

最后发现官网一个细节

坑3

恨不得打自己一顿!第三次尝试,把代码改成如下:

const fetch = _.debounce(function (config,resolve,reject) {

axios(config).then(data=>{

resolve(data)

}).catch(err=>{

reject()

})

}, 500)

export default function(config){

return new Promise((resolve, reject) => {

fetch(config, resolve, reject)

})

}

这一回,终于成功了,在500ms内的多次点击,只会取最后一次请求发送。感动(ಥ _ ಥ)

坑4

细想了下,好像需求不太对,情况是:甲方网络卡,点击后请求未完成的时候,进行了第二次点击发送请求。这个好像和我做的防抖没啥关系???…………

还好,这个好解决,添加了一个变量,用来存储每次请求的接口数据,在请求时判断当前接口是否在请求中(即是否存在当前数据),在响应成功后进行删除。 —— 这个和防抖好像差不多???- 防抖对请求和响应都只调用一次,这个方法需要每次在请求拦截器中判断

以上情况,大概花了2分钟(重点)

坑5

就在以为完美解决了问题,打包发布测试版后,满心欢喜(再一次欢喜)的想和产品报告时,问题出现了……

我?????这又是什么情况,刚才不还好好的么。检查了代码发现:

不报bug的写法

报bug的写法

同学们,项目格式化和规范化真的很重要!

于是继续各种百度各种咨询,最终改为:

function promise(config,methods, type){

return new Promise((resolve, reject) => {

fetch(config,type,resolve,reject)

})

}

// 通过向 axios 传递相关配置来创建请求

function http(config){

return promise(config)

}

// 直接执行 GET /POST 请求

http.get = (config)=>{

return promise(config)

}

http.post = (config)=>{

return promise(config)

}

export default http

坑6

嗯,不报错了,接口也请求成功了,可以和产品报告了……等下,为什么我页面上的两个接口,只执行了一个???检查下,查查查,好像没啥毛病??

那是因为!防抖啊! 初始同时加载的请求,防抖他压根不管你接口相不相同,大爱无疆、一视同仁、雨露均沾,它全都一次性给你防了,只取最后一个接口请求,真正的做到了公平公正……

那我花了这么多时间写的东西不能白费呀,让我想想怎么改来继续保留我的防抖功能

  • 判断接口是不是同一个,相同的接口进行防抖,不相同的绕过防抖?但是会有相同地址不同参数的接口同时请求啊!例如枚举接口! —— 失败
  • 那就存储接口的时候,把参数信息存进去?……先不说其他的,就说表单提交这么多字段,机器都想哭 —— 失败
  • 接口请求按顺序进行调用,下一个接口在上一个接口请求后等待500ms再进行请求?用户体验感也太太太太太差了 —— 失败
  • get请求绕过防抖,post请求进行防抖?(我还真这样尝试了……)可能产生不可预见性bug —— 失败

防抖花了我一天的时间,真的要抛弃么😭

最后,删除所有关于debounce防抖功能的代码,只保留我之前花了不到5分钟判断是否在请求中的功能,完美实现了需求

结语

总结下吧,我真的太南了。

  • 没有充分理清楚需要的需求,导致走了弯路
  • 没有及时止损,已经知道有简单的方法,但是因为已经研究了好久,就不舍得放弃
  • 学习了新知识点,还是有收获的
  • 还是因为工作不饱和,闲的,我有大把时间研究新知识,我骄傲😏
  • 碰到的问题还是没法独立解决,还是需要加强学习!
  • 感谢各位被我打扰还是不厌其烦帮我的大佬们

共勉!

以上是 失败的axios防抖 的全部内容, 来源链接: utcz.com/a/21006.html

回到顶部