函数防抖与节流
2019/1/11 Javascript
# 防抖和节流
函数节流的核心是,让一个函数不要执行得太频繁,减少一些过快的调用来节流。
函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次。
# 应用条件
发送一个 ajax 表单,给一个 button 绑定 click 事件,并且监听触发 ajax 请求。如果是 debounce,则用户不管点多少次,都只会发送一次请求;如果是 throttle,不断点击的过程中会间隔发送请求。这时候最好使用 debounce. 监听滚动事件判断是否到页面底部自动加载更多,如果是 debounce,则只有在用户停止滚动的时候的才会判断是否到了底部,如果是 throttle,则页面滚动的过程中会间隔判断是否到达底部。 此时最好使用 throttle
# 函数防抖
/**
* 防抖函数,返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
*
* @param {function} func 回调函数
* @param {number} wait 表示时间窗口的间隔
* @param {boolean} immediate 设置为ture时,是否立即调用函数
* @return {function} 返回客户调用函数
*/
const debounce = (func, wait = 1000, immediate = true) => {
let timer;
let context;
let args;
// 延迟执行函数
const later = () =>
setTimeout(() => {
// 延迟函数执行完毕,清空缓存的定时器序号
timer = null;
// 延迟执行的情况下,函数会在延迟函数中执行
// 使用到之前缓存的参数和上下文
if (!immediate) {
func.apply(context, args);
context = null;
args = null;
}
}, wait);
// 这里返回的函数是每次实际调用的函数
return (...params) => {
// 如果没有创建延迟执行函数(later),就创建一个
if (!timer) {
timer = later();
// 如果是立即执行,调用函数
// 否则缓存参数和调用上下文
if (immediate) {
func.apply(this, params);
} else {
context = this;
args = params;
}
// 如果已有延迟执行函数(later),调用的时候清除原来的并重新设定一个
// 这样做延迟函数会重新计时
} else {
clearTimeout(timer);
timer = later();
}
};
};
export default debounce;
# 函数节流
const throttle = (func, delay) => {
let last;
let deferTimer;
return (...args) => {
const now = +new Date();
if (last && now < last + delay) {
clearTimeout(deferTimer);
deferTimer = setTimeout(() => {
last = now;
func.apply(this, args);
}, delay);
} else {
last = now;
func.apply(this, args);
}
};
};
export default throttle;