业务中实际使用节流/防抖以及手写实现

实际业务场景

在电商的实际业务中,比如提现、提交一些评价,还有很多场景的按钮点击,都需要做一下按钮的点击限制,假如说用户疯狂点击提交按钮且服务端没有做任何限制,数据请求就会重复,可能同样的评价重复提交了好几次;
这里就以提交商品评价和提现为例:
提交商品评价

节流和防抖的区别

节流:throttle

节流一般用在按钮点击、提交的时候,用户可能用疯狂点击这个按钮,假设我们可以限制,在5秒钟内无论点击多快多少次,只有第1次生效,5秒钟后再次点击按钮,第2次才会生效。

防抖:debounce

防抖一般用在实时搜索的场景,假如我们要搜索一个疾病:’胃溃疡急性胃穿孔’,没有防抖的话,当你刚打完第一个字’胃’,就请求了一次接口,打完第二个字’溃’,也进行了请求,所以对于性能非常不友好;我们希望完成输入一个词汇后,再进行请求,那么就需要防抖,假设当我1秒钟内再没有输入的动作,再执行请求。如下图:
疾病搜索
搜索结果

解决方案

现成的插件轮子

npm上面一个只有80kb大小的插件,直接安装使用即可:点击查看

手写一个

都只是简易版本,不针对全面、复杂的业务情况,重点在于说明逻辑和思路而已

节流:throttle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* @description: 节流函数
* @param {Number} time: 多长时间内可以点击生效
* @param {Function} func: 执行的函数
*/
const throttleFunc = function(time, func) {
let initTime = 0
const _fn = function () {
const _self = this
const _params = arguments
const nowTime = Date.now()

if (nowTime - initTime >= time) { // 可以执行
func.apply(_self, _params) //将所有的参数带进来,并且用apply改变一下this的指向
initTime = Date.now() //可以成功执行,则将初始时间重置
}
}
return _fn
}

防抖:debounce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* @description: 防抖函数
* @param {Number} time: 多长时间后才能生效
* @param {Function} func: 执行的函数
*/
const debounceFunc = function(time, func) {
let Timer = null
const _fn = function () {
const _self = this
const _params = arguments

if(Timer){ //只要执行函数,就将现有定时器清空
clearTimeout(Timer)
}

Timer = setTimeout(_ => { //等待一段时间后,才执行
func.apply(_self, _params) //将所有的参数带进来,并且用apply改变一下this的指向
clearTimeout(Timer)
}, time)
}
return _fn
}

总结

自己手动实现的话,不论是节流还是防抖重点在于执行时机,以及内部函数的this指向问题和外部传入的参数;
这里也留一个思考问题,为什么func后面要使用apply,而不是call呢?两者的区别在哪里?


业务中实际使用节流/防抖以及手写实现
https://liujiaweb.cn/posts/4862.html
作者
Liu Jia
发布于
2021年2月2日
许可协议