实现Debounce和Throttle

debounce函数所做的事情是:强制一个函数在某个连续的时间段内只执行一次,哪怕他本来会被调用多次,我们希望在用户停止某个操作一段时间之后才执行相应的监听函数,而不是在用户操作的过程当中,浏览器触发多少事件,就执行多少监听函数。

//弹跳函数
function debounce(fn,delay){
    var timer
    return function(){
        var _this = this;
        var args = arguments;

        //每次这个返回函数被调用,就清楚定时器,保证fn不被执行
        clearTimeout(time);
        //当返回的函数被最后一次调用(用户停止了某个连续动作),延迟delay毫秒后执行fn
        timer = setTimeout(function(){
            fn.apply(_this,args);
        },delay)
    }
}
//调用
$(document).on('mouvemove', debounce(function(e) {
    // 代码
}, 250))

原理:debounce返回一个闭包,这个闭包会被连续平凡的调用,但在闭包内部却显示了原始函数fn的执行,强制fn只在连续操作停止后执行一次。

使用场景:

1 比如,在某个 3s 的时间段内连续地移动了鼠标,浏览器可能会触发几十(甚至几百)个 mousemove 事件,不使用 debounce 的话,监听函数就要执行这么多次;如果对监听函数使用 100ms 的“去弹跳”,那么浏览器只会执行一次这个监听函数,而且是在第 3.1s 的时候执行的。
2 根据用户的输入实时向服务器发 ajax 请求获取数据。我们知道,浏览器触发 key* 事件也是非常快的,即便是正常人的正常打字速度,key* 事件被触发的频率也是很高的。以这种频率发送请求,一是我们并没有拿到用户的完整输入发送给服务器,二是这种频繁的无用请求实在没有必要。
更合理的处理方式是,在用户“停止”输入一小段时间以后,再发送请求。那么 debounce 就派上用场了:

$('input').on('keyup', debounce(function(e) {
    // 发送 ajax 请求
}, 300))

Throttle就是固定函数执行的速率,即所谓的“节流”。

/**
*
* @param fn {Function}   实际要执行的函数
* @param delay {Number}  执行间隔,单位是毫秒(ms)
*
* @return {Function}     返回一个“节流”函数
*/

function throttle(fn, threshhold) {

  // 记录上次执行的时间
  var last

  // 定时器
  var timer

  // 默认间隔为 250ms
  threshhold || (threshhold = 250)

  // 返回的函数,每过 threshhold 毫秒就执行一次 fn 函数
  return function () {

    // 保存函数调用时的上下文和参数,传递给 fn
    var context = this
    var args = arguments

    var now = +new Date()

    // 如果距离上次执行 fn 函数的时间小于 threshhold,那么就放弃
    // 执行 fn,并重新计时
    if (last && now < last + threshhold) {
      clearTimeout(timer)

      // 保证在当前时间区间结束后,再执行一次 fn
      timer = setTimeout(function () {
        last = now
        fn.apply(context, args)
      }, threshhold)

    // 在时间区间的最开始和到达指定间隔的时候执行一次 fn
    } else {
      last = now
      fn.apply(context, args)
    }
  }
}

如果还是不能完全体会 debouncethrottle 的差异,可以到 这个页面 看一下两者可视化的比较。

debounce 强制函数在某段时间内只执行一次,throttle 强制函数以固定的速率执行。在处理一些高频率触发的 DOM 事件的时候,它们都能极大提高用户体验。

原文地址:https://blog.csdn.net/redtopic/article/details/69396722

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第二十二章:高级技巧 本章内容: 使用高阶函数 防篡改对象 Yieding Timers 22.1 高级函数 22...
    穿牛仔裤的蚊子阅读 658评论 0 1
  • 前言 props与state都是用于组件存储数据的一js对象,前者是对外暴露数据接口,后者是对内组件的状态,它们决...
    itclanCoder阅读 2,191评论 0 0
  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    怡宝丶阅读 2,609评论 0 7
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,144评论 1 32
  • 这个假期,没有工作的压力,践行情况也很不错,具体如下: 1.早起早睡,目前早起已经不用闹钟很久了,6点左右就能自然...
    兰卿1阅读 141评论 0 0