函数的防抖和节流
1、函数防抖
应用场景:输入框搜索自动补全事件,频繁操作点赞和取消点赞等等,获取最后一次操作结果并发送给服务器,再比如onscroll,onresize,onmouseover和上述的键盘监听事件
举个栗子:监听一个input框的输入事件,但是大多数情况下,我们不是为了监听用户输了什么,而是想知道用户输到什么时候结束了,所以如果实时监听键盘事件,在每次用户敲击键盘的时候去触发一个函数,这样就多了非常多无用的操作;再比如window.resize事件
//在你的控制台输入以下代码
window.onresize = ()=> {
console.info('onresize');
};
在浏览器运行可以看到 如果我们简单的变化浏览器的大小,控制台会一直打印,这并不是我们需要的,我们往往只需要知道,用户在哪里停下就可以了
* @param {*} method
* @param {*} context 环境
* @param {*} delay 延迟时间
* @param {*} isImmediate 立即执行 默认为true
*/
export function debounce(method,delay=500,isImmediate = true){
let timer = null;
let flag = true
if(isImmediate){
return function () {
if (timer) {
clearTimeout(timer);
timer = null
}
if (flag === true) {
method.apply(this, arguments);
flag = false
}
timer = setTimeout(() => {
flag = true
timer = null
}, delay)
}
}else{
return function() {
clearTimeout(timer);
timer=setTimeout(function(){
method.apply(this);
},delay);
}
}
}
代码意思很明显,这个方法接受你想防抖的函数以及他的上下文,然后在500ms延时之后执行这个函数,若下一次函数在500ms内调用则清除上个定时器然后在延迟500ms执行,函数防抖有效的防止了一个函数被多次调用
再来试试
function fun(){
console.log('onresize')
}
window.onresize = debounce(fun)
把这段代码拷进你的控制台然后在试试,是不是好多了
2、函数节流
相比于防抖,节流就是在让函数在特定的时间内只执行一次
应用场景:
- 轮播图快速点击
- DOM 元素的拖拽功能实现(mousemove)
- 搜索联想(keyup)
- 计算鼠标移动的距离(mousemove)
- Canvas模拟画板功能(mousemove)
- 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce
后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次.
// 函数节流
export function throttle(f, t, im = false){
let flag = true;
return (...args)=>{
if(flag){
flag = false
im && f(...args)
setTimeout(() => {
!im && f(...args)
flag = true
},t)
}
}
}
用一个flag让该函数在500ms内只执行一次
3、区别
他们都是可以防止一个函数被无意义的高频率调用
区别在于:
函数防抖:指在时间n内,函数被触发多次,但是只执行一次,执行最新的触发。也就是在时间n内,碰到新的触发,就清除之前的,重新计时。
函数节流:是确保函数特定的时间内至多执行一次。当持续触发某个事件时,会有规律的每隔时间n就执行一次函数。