搜索
您的当前位置:首页正文

js防抖、节流(立即执行/非立即执行 + 立即取消等待)

来源:欧得旅游网











一、防抖(立即执行/非立即执行 + 立即取消等待)

  • 什么是防抖:一个事件在触发后,设置定时器,若n秒内该事件没有再次发生,那么执行这个函数,如果n秒内该事件再次发生了,那么定时器重新开始计时。

  • 应用
    • 每次 resize / scroll 触发统计事件
    • 文本输入的验证 (连续输入文字后发送AJAX请求进行验证,验证一次就好)



1.1 非立即执行版

//防抖(非立即执行)
function debounce_1(fn,wait){
  let timerId = null;
  return function(){
    clearTimeout(timerId);
    timerId = setTimeout(() => {
      fn.apply(this,arguments)
    },wait)
  }
}




1.2 立即执行版

//防抖(立即执行)
function debounce_2(fn,wait){
  let timerId = null;
  let flag = true;
  return function(){
    clearTimeout(timerId);
    if(flag){
      fn.apply(this,arguments);
      flag = false
      }
    timerId = setTimeout(() => { flag = true},wait)
  }
}




1.3 合并版

//防抖(合并版)
function debounce_merge(fn,wait = 500,isImmediate = false){
  let timerId = null;
  let flag = true;
  if(isImmediate){
    return function(){
      clearTimeout(timerId);
      if(flag){
        fn.apply(this,arguments);
        flag = false
        }
      timerId = setTimeout(() => { flag = true},wait)
    }
  }
  return function(){
    clearTimeout(timerId);
    timerId = setTimeout(() => {
      fn.apply(this,arguments)
    },wait)
  }
}

1.4 合并版 + 立即取消等待

//防抖(合并版)
export const debounce = function (fn, wait = 500, isImmediate = false) {
    // 计时器
    let timerId = null;

    // flag为真时立即执行
    let flag = true;
    let resultFunc = null;


    if (isImmediate) {
        // 立即执行
        //  例如:用户在输入框中输入字符,输入第一个字符时,立即执行一次
        // 之后,最终间隔超过2秒后,才执行补全查询

        resultFunc = function () {
            let context = this;

            clearTimeout(timerId);
            if (flag) {
                fn.apply(context, arguments);
                flag = false
            }
            timerId = setTimeout(() => {
                flag = true
            }, wait)
        }

        resultFunc.cancel = function () {
            // 例如,用户打字很快,然后输入完成后,未达到两秒钟就移动鼠标
            // 此时输入框失去焦点,触发取消等待方法,立刻执行补全查询操作并显示结果出来

            console.log("立即取消等待")
            clearTimeout(timerId);
            flag = true;
        }

    } else {
        // 不立即执行 
        //  例如:用户在输入框中输入字符,最终间隔超过2秒后,才执行补全查询

        resultFunc = function () {
            let context = this;

            clearTimeout(timerId);
            timerId = setTimeout(() => {
                fn.apply(context, arguments)
            }, wait)
        }

        resultFunc.cancel = function () {
            console.log("立即取消等待");
            clearTimeout(timerId);
        }
    }
    return resultFunc;
}






二、节流(立即执行/非立即执行 + 立即取消等待)

  • 什么是节流:一个事件在n秒内被多次触发,但绑定的函数在期间只会执行一次(也就是降低函数的执行频率)
  • 应用
    • 与mousemove keyup/keydown 等相密切联系的函数
    • 输入框发送补全查询
    • 秒杀、抢卷按钮,按下一次后,接下来几秒不让用户继续按(也可用锁实现)



2.1 非立即执行版

//定义函数
//节流(非立即执行)
function throttle_1(fn,wait){
  let flag = true;
  return function(){
    if(flag == true){
      flag = false
      var timer = setTimeout(() => {
        fn.apply(this,arguments)
        flag = true
      },wait)
    }
  }
}



2.2 立即执行版

//节流(立即执行)
function throttle_2(fn,wait){
  var flag = true;
  var timer = null;
  return function(){
    if(flag) {
      fn.apply(this,arguments);
      flag = false;
      timer = setTimeout(() => {
        flag = true
      },wait)
    }
  }
}



2.3 合并版

//节流(合并)
function throttle_merge(fn,wait = 500,isImmediate = false){
  let flag = true;
  let timer = null;
    
  if(isImmediate){
    return function(){
      if(flag) {
        fn.apply(this,arguments);
        flag = false;
        timer = setTimeout(() => {
          flag = true
        },wait)
      }
    }
  }
    
  return function(){
    if(flag == true){
      flag = false
      var timer = setTimeout(() => {
        fn.apply(this,arguments)
        flag = true
      },wait)
    }
  }
}

2.4 合并版 + 立即取消等待

//节流(合并)
export const throttle = function (fn, wait = 500, isImmediate = false) {
    let flag = true;
    let timer = null;

    let resultFunc = null;

    if (isImmediate) {
        // 立即执行
        resultFunc = function () {
            if (flag) {
                fn.apply(this, arguments);
                flag = false;
                timer = setTimeout(() => {
                    flag = true
                }, wait)
            }
        }

        resultFunc.cancel = function () {
            console.log("立即取消等待")
            clearTimeout(timer)
        }
    } else {
        // 不立即执行
        resultFunc = function () {

            if (flag == true) {
                flag = false
                timer = setTimeout(() => {
                    fn.apply(this, arguments)
                    flag = true
                }, wait)
            }
        }

        resultFunc.cancel = function () {
            console.log("立即取消等待")
            clearTimeout(timer);
            flag = true;
        }
    }

    return resultFunc;

}

因篇幅问题不能全部显示,请点此查看更多更全内容

热门图文

Top