截流函数

2021-02-27  本文已影响0人  susu一口酥
/**
* 截流函数
* @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;
}
上一篇 下一篇

猜你喜欢

热点阅读