vivatoviva / Interview-Frontend-2020

欢迎star、在对应的ussues沉淀知识
17 stars 2 forks source link

函数节流防抖原理 #10

Open vivatoviva opened 5 years ago

vivatoviva commented 5 years ago

函数防抖(debounce):函数经过固定的时间进行调用,如果在这固定的时间内重新调用函数,则会重新计算调用时间。(函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次)

函数节流(throttle):函数调用的时候设定一个执行周期,当调用动作的时刻大于执行周期则执行该动作,然后进入下一个周期。(让一个函数不要执行得太频繁,减少一些过快的调用来节流)

debounce 实现代码:

两种思路如下:

// fun节流函数
// wait 间隔时间
// 是否立即执行,最后不执行,只在最开始执行一次
function debounce(func, wait = 100, immediate){
  var timeout, args, context, timestamp, result;

  function later() {
    var last = Date.now() - timestamp;

    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      if (!immediate) {
        result = func.apply(context, args);
        context = args = null;
      }
    }
  };

  var debounced = function(){
    context = this;
    args = arguments;
    timestamp = Date.now();
    var callNow = immediate && !timeout;
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }

    return result;
  };

  debounced.clear = function() {
    if (timeout) {
      clearTimeout(timeout);
      timeout = null;
    }
  };

  debounced.flush = function() {
    if (timeout) {
      result = func.apply(context, args);
      context = args = null;

      clearTimeout(timeout);
      timeout = null;
    }
  };

  return debounced;
};

throttle实现方式如下:

function throttle(fun, wait) {
  let timeout, timestamp, last;

  function setTime(...args) {
    const delayTime = last ? +new Date() - last : 0;
    return setTimeout(() => {
      last = +new Date();
      fun.apply(this, args);
      clearTimeout(timeout);
      timeout = null;
    }, wait - delayTime);
  }

  return function (...args) {
    timestamp = +new Date();
    // 考虑客户端主动更改时间(last > timestamp),因为我们封装的是立即调用函数,所以在客户端更改时间之后,应该立即调用函数,并且清除定时器
    if (!last || (timestamp - last >= wait && !timeout) || last > timestamp) {
      clearTimeout(timeout);
      timeout = null;
      last = timestamp;
      fun.apply(this, args);
    }

    if(!timeout) {
      timeout = setTime.apply(this, args);
    }
  }
}

问题: