绩效考核手机版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

86 lines
2.8 KiB

/**
* @description: 函数节流
* @param {Function} func 回调函数
* @param {Number} wait 等待时间
* @param {{leading:Boolean,trailing:Boolean}} options
* @return {Function}
* @example const func = throttle(()=>console.log(1),100);
*/
export default function throttle(func, wait = 100, options) {
let timeout, context, args, result;
// 上一次执行回调的时间戳
let previous = 0;
// 无传入参数时,初始化 options 为空对象
if (!options) options = {};
const later = function () {
// 当设置 { leading: false } 时
// 每次触发回调函数后设置 previous 为 0
// 不然为当前时间
previous = options.leading === false ? 0 : Date.now();
// 防止内存泄漏,置为 null 便于后面根据 !timeout 设置新的 timeout
timeout = null;
// 执行函数
result = func.apply(context, args);
if (!timeout) context = args = null;
};
// 每次触发事件回调都执行这个函数
// 函数内判断是否执行 func
// func 才是我们业务层代码想要执行的函数
function throttled() {
// 记录当前时间
const now = Date.now();
// 第一次执行时(此时 previous 为 0,之后为上一次时间戳)
// 并且设置了 { leading: false }(表示第一次回调不执行)
// 此时设置 previous 为当前值,表示刚执行过,本次就不执行了
if (!previous && options.leading === false) previous = now;
// 距离下次触发 func 还需要等待的时间
const remaining = wait - (now - previous);
context = this;
args = arguments;
// 要么是到了间隔时间了,随即触发方法(remaining <= 0)
// 要么是没有传入 {leading: false},且第一次触发回调,即立即触发
// 此时 previous 为 0,wait - (now - previous) 也满足 <= 0
// 之后便会把 previous 值迅速置为 now
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
// clearTimeout(timeout) 并不会把 timeout 设为 null
// 手动设置,便于后续判断
timeout = null;
}
// 设置 previous 为当前时间
previous = now;
// 执行 func 函数
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
// 最后一次需要触发的情况
// 如果已经存在一个定时器,则不会进入该 if 分支
// 如果 {trailing: false},即最后一次不需要触发了,也不会进入这个分支
// 间隔 remaining milliseconds 后触发 later 方法
timeout = setTimeout(later, remaining);
}
return result;
}
// 手动取消
throttled.cancel = function () {
clearTimeout(timeout);
previous = 0;
timeout = context = args = null;
};
return throttled;
}