遇到一个需求,页面需要加载一个数据表,但是请求的特别慢,如果用户多次点击按钮,那么此时就会不断触发这个请求,因为不断发请求,所以会导致页面不断乱刷新,可以说体验感特别差。所以一直在思考怎么解决这个bug。突然想到防抖和节流,我之前也一直没有搞清楚,这次一次性搞清,再来试图解决一下页面这个bug。
函数防抖
首先考虑的是防抖,什么是防抖。在页面中,诸如click,mousemove这些事件可能在短时间内会被多次执行,比如多次点击一个按钮,那么如果一次点击就要发一次请求,则会造成内存的过度使用。所以我们监听一个定时器,当定时器被点击的时候我们用一个定时器去监听,设置一定的时间后再去触发事件。这样的情况下,如果这个按钮再次被点击,那么因为监听了定时器,此时定时器会被替代,重新开始计算时间,这就是函数防抖的原理,这里给出原始版本的函数防抖:
let timer = ""
export function debounce(fn,time){
window.clearTimeout(timer);
timer = setTimeout(()=>{
fn()
},time)
}
但是以上的代码,time是一个外层的变量,这样会污染环境,所以我们考虑用闭包的方式把变量包含在父作用域中,这样变量一直会限制在局部作用域中而不会污染整个环境了。
export function debounce(fn,time){
let timer;
return ()=>{
const _this = this;
if (timer) clearTimeout(timer)
timer = setTimeout(()=>{
fn.apply(_this)
},time)
}
}
函数节流
对上面减少触发次数不同的思路是节流。让函数在一段时间内只执行一次,这是这个思想的宗旨。比如之前的鼠标点击触发的请求,我们可以采用节流函数进行封装,这样能有效的减少点击之后发送的请求个数。 代码跟之前的防抖很类似。
export const throttle = (fn,time)=>{
let timer
return ()=>{
const _this = this
if (timer) return
timer = setTimeout(()=>{
fn.call(_this)
//不同点在于触发后就清楚timer,从而使得下次进入函数的时候能再次触发一个节流函数
timer = null
},time)
}
}
以上就是防抖和节流的思想和实现方式了,希望对我的项目有帮助