如何实现函数节流

这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

hi 我是小十七_,新年快乐,今天是大年初六,明天是上班的日子了,祝大家开工大吉,保持好心态,之前整理了如何实现函数节流,在这里分享给大家。

为什么需要函数节流

类似于 resizemousemove 之类的事件,不需要用户特意去做什么操作,也会在短时间内执行很多次,DOM 操作是非常耗性能的,如果在这些函数的监听事件中操作 DOM,页面会变卡变慢,甚至在 ie 中可能会失去响应

函数节流的概念

让函数不能在连续事件内过于频繁的调用,在上一次调用之后,只有过了规定的时间间隔,才能进行下一次的调用。

简单实现

function test(fn, time){
  // 内部定义 timer 变量,所有返回的函数保持对这个变量的引用
  var timer = null;
  return function(){
    var context = this, args = arguments;
    // 如果再一次执行 resize 函数,先清空上一次的定时器,否则就会执行
    clearTimeout(timer);
    // 定义新的定时器,执行实际内容
    timer = setTimeout(function(){
      fn.apply(context, args);
    }, time)
  }
}
function handleResize(){console.log('-- resize --')}
window.resize = test(handleResize, 100); // 等于的是 test 执行返回的函数,保持对 test 内部的 timer 变量
复制代码

进一步实现

简单实现中,如果监听的是 mousemove 事件,用户频繁拖动一个div的时候,中间拖动的过程会不断的创建和清空定时器,也就是实际的代码不会执行,在用户稍等一会停止拖动才会执行。所以需要给事件设置一个最小执行的间隔,如果大于这个间隔的话,事件一定需要被执行一次。

function test(fn, time, mustTime){
  // 内部定义 timer,start_time 变量,所有返回的函数保持对这个变量的引用
  var timer = null, start_time = null;
  return function(){
    var context = this, args = arguments, current_time = new Date().getTime();
    // 如果再一次执行 resize 函数,先清空上一次的定时器,否则就会执行
    clearTimeout(timer);
    // 如果当前执行的间隔时间大于设定的必须执行时间,执行函数
    if(current_time-start_time>=mustTime){
      fn.apply(context, args);
      start_time = current_time;  // 重置开始时间
    }else{
	    // 定义新的定时器,执行实际内容
	    timer = setTimeout(function(){
	      fn.apply(context, args);
	    }, time)
    }
  }
}
复制代码

也可以通过 lodash 的 debounce 简单实现

codepen.io/ubuntugx/pe…

猜你喜欢

转载自juejin.im/post/7061554096041361444