节流 和 防抖 简介
在用户进行浏览器页面的操作时,可能会发生一段时间内(如1s内),连续、频繁点击某个操作按钮,导致频繁操作dom或者向后台发出请求,可能会造成页面卡顿或者服务器拥堵。针对此种情况,可以使用js的 节流 和 防抖 来解决。
节流 和 防抖 这两种方式的实现原理都是利用 setTimeOut 定时器来实现的,将用户的操作延迟执行。
节流 和 防抖 区别
节流,采用“间隔一段时间后执行”,即 第一次触发时,先创建一个定时器,在一定时间后再执行触发事件,同时将定时器置为空,若在一定时间内(比如1s内)再次触发,则会判断定时器是否存在,如果存在,则不再创建新的定时器(后续的触发事件不会执行);
防抖,采用“延迟执行触发,并清除上一次的定时器”,即 第一次触发时,先创建一个定时器,在一定时间后再执行触发事件,若在一定时间内(比如1s内)再次触发,则会清除之前的定时器,重新新建一个定时器;这样会有一个缺点,就是 若在一段时间内不停地触发事件,那么该事件的执行会被无限期地延后。
应用场景
-
节流
- 防止表单提交时重复多次触发事件;
-
防抖
-
窗口resize需计算窗口的大小时,需等用户的拖拽事件完成后执行计算方法;
-
input 输入框的实时查询事件,在用户不断输入的过程中不触发查询,等用户输入完停止一段时间后再触发
-
代码实现
- 节流
function clickFn() {
console.log('clickFn');
}
// 节流,一段时间内只能触发一次函数,若触发多次,则只有一次生效(相当于执行这段时间内第一次点击的事件)
function dealFn(func, time) {
let timer = null;
return function() {
let that = this;
if(!timer) {
timer = setTimeout(() => {
func.call(that);
timer = null;
}, time)
}
}
}
let submitClick = dealFn(clickFn, 1000);
submitClick();
submitClick();
setTimeout(()=> {
console.log("...");
submitClick();
}, 1000);
- 防抖
function clickFn() {
console.log('clickFn');
}
// 防抖,一段时间内触发多次函数时,每次触发都延迟函数调用,并在下一次触发时清除之前的定时器(相当于执行这段时间内最后一次点击的事件)
// 每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法
// 缺点:如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟
function dealFn(func, time) {
let timer = null;
return function() {
let that = this;
clearTimeout(timer);
timer = setTimeout(() => {
func.call(that);
}, time)
}
}
let submitClick = dealFn(clickFn, 1000);
submitClick();
submitClick();
setTimeout(()=> {
console.log("...");
submitClick();
}, 1000);
扩展知识点
1、call 和 apply
详见 javaScript---bind、call、apply
2、闭包
之所以在后续的方法调用(submitClick()
)时,能删除之前调用时定义的 timer,是因为 js 的闭包,使得对于这些调用来说,timer 成为了一个“全局变量”。