手写防抖节流

1.什么是防抖?

事件响应函数(doSomeThing)在一段时间(await)之后才执行,如果这段时间内再次调用函数,则重新计算时间。

应用场景:

1,scroll时间滚动触发

2,搜索框输入查询

3,表单验证

4,按钮提交事件

5,浏览器窗口缩放,resize事件

一般情况包括频繁操作,回调,发生ajax造成页面性能消耗,卡顿现象时,会用到防抖操作

手写防抖需要解决的问题:

1,this的指向问题

2,参数的传递event

3,防抖函数的第三个参数,控制只要触发立即执行

4,取消防抖操作

手写函数:

function debounce(func, await, immediate) {
  let timeout, result;
  let debounced = function () {
    let that = this;
    let args = arguments;
    clearTimeout(timeout);
    if (immediate) {
      let callNow = !timeout;
      timeout = setTimeout(function () {
        timeout = null;
      }, await);
      //给func添加一个返回结果
      //立即执行
      if (callNow) result = func.apply(that, args);
    } else {
        //不会立即执行
      timeout = setTimeout(function () {
        func.apply(that, args);
      }, await);
    }
    return result;
  };
  //添加一个取消防抖操作的函数
  debounced.cancel = function () {
    clearTimeout(timeout);
    timeout = null;
  };
  return debounced;
}

let count = 0;
let box = document.querySelector(".box");
let btn = document.querySelector("#btn");
let doSome = debounce(doSomeThing, 3000);
function doSomeThing(e) {
  box.innerHTML = count++;
  console.log(count);
}
box.onmousemove = doSome;
btn.onclick = function () {
  doSome.cancel();
};

 

2,什么是节流

原理:如果持续触发事件,每隔一段时间,只执行一次事件

应用场景:

1.DOM元素的拖拽功能实现

2.射击游戏

3.计算鼠标移动距离

4.监听scroll滚动事件

// 1.使用时间戳实现节流函数
// 第一次调用,最后一次不调用触发函数,leading:true,training:false
function throttle(func, await) {
  let that,arguments;
  let old = 0;
  return function () {
      that=this
      args=arguments
    let now = Date.now();
    if (now - old > await) {
        //立即执行
      func.apply(that,args);
      old=now
    }
  };
}
//2.使用定时器完成
//第一次不会触发,最后一次会触发,leading:false,training:true
function throttle(func, await) {
  let that, args, timeout;
  return function () {
    that = this;
    args = arguments;
    if (!timeout) {
      timeout = setTimeout(function () {
        timeout = null;
        func.apply(that, args);
      }, await);
    }
  };
}
//3.两个方法结合一下实现第一次触发,最后一次也触发,leading:true,training:true
function throttle(func, await) {
  let that, args, timeout;
  let old = 0;
  return function () {
    that = this;
    args = arguments;
    let now = Date.now();
    if (now - old > await && !timeout) {
      func.apply(that, args);
      old = now;
      console.log(1222);
    }

    if (!timeout) {
      timeout = setTimeout(function () {
        timeout = null;
        func.apply(that, args);
        old = Date.now();
        console.log(2333);
      }, await);
    }
  };
}
//4.实现第三个参数
function throttle(func, await, options) {
  let that, args, timeout;
  let old = 0;
  if (!options) options = {};
  return function () {
    that = this;
    args = arguments;
    let now = Date.now();
    if (options.leading === false && !old) {
      old = now;
    }
    //首次触发立即执行
    if (now - old > await && !timeout) {
      func.apply(that, args);
      old = now;
      console.log(1222);
    }
    if (!timeout && options.traing !== false) {
      timeout = setTimeout(function () {
        timeout = null;
        func.apply(that, args);
        old = Date.now();
        console.log(2333);
      }, await);
    }
  };
}

上一篇:亲测!ROS安装过程中rosdep init && rosdep update timeout的解决办法


下一篇:sendDefaultImpl call timeout