防抖和节流的目的都是为了减少不必要的计算,不浪费资源,只在适合的时候再进行触发计算。
1. 函数防抖(debounce)
定义
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时;典型的案例就是输入搜索:输入结束后n秒才进行搜索请求,n秒内又输入的内容,就重新计时。实现原理
函数防抖的基本思想是设置一个定时器,在指定时间间隔内运行代码时清楚上一次的定时器,并设置另一个定时器,知道函数请求停止并超过时间间隔才会执行。使用场景
文本框输入搜索(连续输入时避免多次请求接口)代码实现
/*
* debounce:实现函数的防抖(目的是频繁触发中只执行一次)
* @params
* func:需要执行的函数
* wait:检测防抖的间隔频率
* immediate:是否是立即执行(如果为TRUE是控制第一次触发的时候就执行函数,默认FALSE是以最后一次触发为准)
* @return
* 可被调用执行的函数
*/
function debounce(func, wait = 500, immediate = false) {
let timer = null;
return function anonymous(...params) {
let now = immediate && !timer;
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
// 执行函数:注意保持THIS和参数的完整度
!immediate ? func.call(this, ...params) : null;
}, wait);
now ? func.call(this, ...params) : null;
};
}
2. 函数节流(throttle)
定义
规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效; 典型的案例就是鼠标不断点击触发,规定在n秒内多次点击只有一次生效。实现原理
其原理是用时间戳来判断是否已到回调该执行时间,记录上次执行的时间戳,然后每次触发 scroll 事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经到达 规定时间段,如果是,则执行,并更新上次执行的时间戳,
使用场景
resize、scroll、mousemove等事件触发监听
- 代码实现
/*
* throttle:实现函数的节流(目的是频繁触发中缩减频率)
* @params
* func:需要执行的函数
* wait:自己设定的间隔时间(频率)
* @return
* 可被调用执行的函数
*/
function throttle(func, wait = 500) {
let timer = null,
previous = 0; //记录上一次操作时间
return function anonymous(...params) {
let now = new Date(), //当前操作的时间
remaining = wait - (now - previous);
if (remaining <= 0) {
// 两次间隔时间超过频率:把方法执行即可
clearTimeout(timer);
timer = null;
previous = now;
func.call(this, ...params);
} else if (!timer) {
// 两次间隔时间没有超过频率,说明还没有达到触发标准呢,设置定时器等待即可(还差多久等多久)
timer = setTimeout(() => {
clearTimeout(timer);
timer = null;
previous = new Date();
func.call(this, ...params);
}, remaining);
}
};
}