一、防抖
防抖函数的作用
防抖函数的作用就是控制函数在一定时间内的执行次数。防抖意味着 N 秒内函数只会被执行一次,如果 N 秒内再次被触发,则 重新 计算延迟时间。
防抖函数的实现
- 事件第一次触发时,timeout 是 null,调用 later(),若 immediate 为true,那么立即调用 func.apply(this, params);如果 immediate 为 false,那么过 wait 之后,调用 func.apply(this, params)。
- 事件第二次触发时,如果 timeout 已经重置为 null (即 setTimeout 的倒计时结束),那么流程与第一次触发时一样,若 timeout 不为 null (即 setTimeout 的倒计时未结束),那么清空定时器,重新开始计时。
function debounce(func, wait, immediate = true) {
let timeout, result;
// 延迟执行函数
const later = (context, args) => setTimeout(() => {
timeout = null;// 倒计时结束
if (!immediate) {
// 执行回调
result = func.apply(context, args);
context = args = null;
}
}, wait);
let debounced = function (...params) {
if (!timeout) {
timeout = later(this, params);
if (immediate) {
// 立即执行
result = func.apply(this, params);
}
} else {
clearTimeout(timeout);
// 函数在每个等待时延的结束被调用
timeout = later(this, params);
}
return result;
}
// 提供在外部清空定时器的方法
debounced.cancel = function () {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
immediate 为 true 时,表示函数在每个等待时延的开始被调用。immediate 为 false 时,表示函数在每个等待时延的结束被调用。
防抖的应用场景
搜索框输入查询,如果用户一直在输入中,没有必要不停地调用去请求服务端接口,等用户停止输入的时候,再调用,设置一个合适的时间间隔,有效减轻服务端压力。
表单验证。
按钮提交事件。
浏览器窗口缩放,resize 事件 (如窗口停止改变大小之后重新计算布局) 等。
二、节流
节流函数的作用
节流函数的作用是规定一个单位时间,在这个单位时间内最多只能触发一次函数执行,如果这个单位时间内多次触发函数,只能有一次生效。
节流函数的实现
function throttle(func, wait, options = {}) {
var timeout, context, args, result;
var previous = 0;
var later = function () {
previous = options.leading === false ? 0 : (Date.now() || new Date().getTime());
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
var throttled = function () {
var now = Date.now() || new Date().getTime();
if (!previous && options.leading === false) previous = now;
//remaining 为距离下次执行 func 的时间
//remaining > wait,表示客户端系统时间被调整过
var remaining = wait - (now - previous);
context = this;
args = arguments;
//remaining 小于等于 0,表示事件触发的间隔时间大于设置的 wait
if (remaining <= 0 || remaining > wait) {
if (timeout) {
// 清空定时器
clearTimeout(timeout);
timeout = null;
}
// 重置 previous
previous = now;
// 执行函数
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
throttled.cancel = function () {
clearTimeout(timeout);
previous = 0;
timeout = context = args = null;
};
return throttled;
}
禁用第一次首先执行,传递 {leading: false} ;想禁用最后一次执行,传递 {trailing: false}。
节流的应用场景
按钮点击事件。
拖拽事件。
onScoll。
计算鼠标移动的距离 (mousemove)。
转载自:《前端之巅》微信公众号
END