截流函数
2021-02-27 本文已影响0人
susu一口酥
- 创建并返回一个像节流阀一样的函数,当重复调用函数的时候,至少每隔 wait毫秒调用一次该函数。对于想控制一些触发频率较高的事件有帮助。
- 默认情况下,throttle将在你调用的第一时间尽快执行这个function,并且,如果你在wait周期内调用任意次数的函数,都将尽快的被覆盖。如果你想禁用第一次首先执行的话,传递{leading: false},还有如果你想禁用最后一次执行的话,传递{trailing: false}。
/**
* 截流函数
* @param fn 需要执行的函数
* @param wait 等待的时间
* @param options leading:false 禁用第一次执行; trailing:false 禁用最后一次执行
*/
const throttle = function(fn,wait,options){
//定义定时器函数、上下文对象、参数、返回结果
let timeout,context,args,result;
// 上一次执行的时间戳
let previos = 0;
//如果没有options,则赋值为空对象
if(!options) options = {};
//定义延迟执行函数
const later = function(){
// 禁用第一次执行,则上次执行为0;否则为当前时间
previos = options.leading === false ? 0 : (new Date()).valueOf();
// 清除timeOut(因为已经是在timeout执行方法内,不需要clear)
timeout = null;
//执行函数
result = fn.apply(context,args);
// 清除定时器
if(!timeout) context = args = null;
}
// 定义截流函数
const throttled = function(){
//获取当前时间戳
let now = (new Date()).valueOf();
//如果没有之前执行的时间并且禁用第一次执行,上次执行时间为当前时间
if(!previos && options.leading === false) previos = now;
// 计算执行等待时间
// 等待时间 - (当前时间 - 上一次执行时间)
let remaining = wait - (now - previos);
// 上下文对象为当前this
context = this;
//args为数组格式
args = arguments;
//如果执行等待时间,不落在wait内,则执行。
if(remaining <= 0 || remaining > wait){
// 如果有计时器
if(timeout){
clearTimeout(timeout);
timeout = null;
}
// 上次执行时间记录为当前
previos = now;
//替换函数this执行
result = fn.apply(context,args);
// 如果没有计时器,清除context 和 args
if(!timeout) context = args = null;
}
//如果没有计时器,并且禁用最后一次执行
else if(!timeout && options.trailing !== false){
timeout = setTimeout(later,remaining);
}
return result;
}
//定义截流函数的取消方法
throttle.cancel = function(){}
//返回截流函数执行
return throttled;
}