函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。
当然,需要判断在触发事件时,是否需要立刻执行回调函数。
/**
* @param fn 回调函数
* @param delay 延迟执行毫秒数
* @param immediate true 指立即执行回调,false 指非立即执行回调
*/
function debounce(fn, delay, immediate) {
let timer = null;
return function () {
let context = this;
let args = arguments;
// 如果此时存在定时器,则取消之前并重新计时
if (timer) {
clearTimeout(timer);
timer = null;
}
if (immediate) {
let _timer = !timer;
timer = setTimeout(function() {
timer = null;
}, delay);
if (_timer) fn.apply(context, args);
}
else {
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
}
}
}
// 调用防抖函数
// foo 回调函数
document.getElementById('xxx').onclick = debounce(foo, 500, true);
函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll、resize、mousemove等函数的事件监听上,通过事件节流来降低事件调用的频率。
同样,函数节流需要判断触发事件时,是否需要立刻执行回调函数。
/**
* @param fn 回调函数
* @param delay 延迟执行毫秒数
* @param immediate true 指立即执行回调,false 指非立即执行回调
*/
function throttle(fn, delay, immediate) {
let preTime = 0;
let timer = null;
return function () {
let context = this;
let args = arguments;
let nowTime = Date.now();
if (immediate) {
if (nowTime - preTime >= delay) {
preTime = nowTime;
fn.apply(context, args);
}
} else {
if(!timer) {
timer = setTimeout(function() {
timer = null;
fn.apply(context, args);
}, delay);
}
}
};
}
// 调用节流函数
// foo 回调函数
document.getElementById('xxx').onmousemove = debounce(foo, 500, true);