防抖 防抖的目的就是防止帕金斯 防止频繁点击

  1. // 最简单的防抖处理:加标识判断即可
  2. let submit = document.querySelector('#submit');
  3. submit.isLoading = false; //标识判断
  4. submit.onclick = function () {
  5. if (this.isLoading) return;
  6. this.isLoading = true;
  7. console.log('数据请求发送...');
  8. setTimeout(() => {
  9. console.log('数据请求成功');
  10. this.isLoading = false;
  11. }, 5000);
  12. };
  1. 具备公共性的防抖函数处理:在用户频繁触发【频繁的规则自己设定】操作的场景中 我们只识别一次即可【识别第一次 识别最后一次】
  2. 规则 300ms内触发两次及以上,就算频繁操作
  3. 在接下来一直点5分钟 只识别一次 这就是属于频繁操作
  4. 一直点 过了3min后我不点了[在最后一次点击500ms内没有点] 识别一次
  5. 过了1s钟,我们又开始频繁点,这是下一次频繁操作 还可以在识别一次

思路

  • 第一次点击:设置定时器 等待300ms
  • 如果300ms没有点击第二次,属于非频繁触发,我们让handle执行一次
  • 如果触发了第二次,属于频繁操作,首先先把上一个没到时间定时器干掉,自己在重新设置一个新的定时器,等待300ms
  • 如果在这个时间内,再次点击,我们再把它干掉,再重新设置一个

关于清空定时器

timer是一个数字,记录当时定时器的编号 clearTimeout(timer):按照编号清除定时器【但是timer的值还是之前的数字】 所以我们一般把timer设置为null;这样做的好处:如果timer=null我们就知道没有定时器 如果不为null则认为定时器还没有清除

        let timer = 10;

        timer = clearTimer(timer);

        console.log(timer);
 const clearTimer = function clearTimer(timer) {
   if (timer) clearTimeout(timer);
   return null;
};  
const debounce = function debounce(func, wait, immediate) {
      if (typeof func !== 'function')
        throw new TypeError('func is not a funciton');
      if (typeof wait === 'boolean') immediate = wait;
      if (typeof wait !== 'number') wait = 300;
      if (typeof immediate !== 'boolean') immediate = false;
      let timer = null;
      return function operate(...params) {
        let now = !timer && immediate,
            result;
        timer = clearTimer(timer);
        timer = setTimeout(() => {
          // 让方法执行的时候THIS是实参和没有debounce之前是一样的
          // 最后执行【结束边界】
          if (!immediate) func.call(this, ...params);
          // 清除最后一次设定的定时器
          timer = clearTimer(timer);
        }, wait);
        //立即执行:【开始边界】
        if (now) result = func.call(this, ...params);
        return result;
      };
};
const handle = function handle() {
  console.log('数据请求发送...');
  setTimeout(() => {
    console.log('数据请求成功');
    this.isLoading = false;
  }, 3000);
};
//submit.onclick = debounce(handle, 300);//func:handle wait:300 immediate:false
//submit.onclick = debounce(handle); //func:handle wait:300 immediate:false
//submit.onclick = debounce(handle, 300, true); //func:handle wait:300 immediate:true
//submit.onclick = debounce(handle, true); //func:handle wait:300 immediate:true
//  submit.onclick=function operate(ev){
//疯狂点击按钮的时候,浏览器会疯狂的触发operate函数执行 我们只需要在operate中 控制handle只执行一次
//}

节流:控制触发的频率

一直点击5min,这样它会间隔500ms触发一次

/*
 * throttle:函数节流
 *  @params
 *    func:自己最终要执行的任务
 *    wait:触发的频率「默认值:500ms」
 *  @return
 *    operate处理函数
 */
const throttle = function throttle(func, wait) {
    if (typeof func !== "function") throw new TypeError('func must be an function!');
    if (typeof wait !== "number") wait = 500;
    let timer = null,
        previous = 0;
    return function operate(...params) {
        let now = +new Date(),
            remaining = wait - (now - previous),
            result;
        if (remaining <= 0) {
            // 两次间隔时间超过500ms了,让方法立即执行
            timer = clearTimer(timer);
            result = func.call(this, ...params);
            previous = +new Date();
        } else if (!timer) {
            // 没设置过定时器等待,则我们设置一个去等待即可
            timer = setTimeout(() => {
                timer = clearTimer(timer);
                func.call(this, ...params);
                previous = +new Date();
            }, remaining);
        }
        return result;
    };
};