js 消抖(debounce)与节流(throttle)

前言

故事发生在与大创的又一次撕逼(日常)中,我方坚定的认为:作为社会主义接班人,节流与消抖的界限是明显的,是不容混肴的,是不可侵犯的!对方辩友坚持地觉得:界限是模糊的,行为是暧昧的,性别是可以忽视的(。。。)。本着凡事要往祖坟上刨的精神,对这两个概念进行了一番深刻的社会主义改造。

定义

节流(throttle)

定义: 如果一个函数持续的,频繁地触发,那么让它在一定的时间间隔后再触发。

感觉像是去排队过安检,当人很多的时候(持续地要进门),安保会隔一段时间放进去几个进行安检(一定时间的间隔)。

消抖(debounce)

定义: 如果一个函数持续地触发,那么只在它结束后过一段时间只执行一次。

像是两个人的对话,A在不停的balabala(持续触发),如果他说话的时候有停顿(一定间隔),但是停顿的时间不够长,就认为A没有说完, 当停顿时间超过一某个范围就认为A说完了,然后B开始回答(响应)。

场景

前提其实都是某个行为持续地触发,不同之处只要判断是要优化到减少它的执行次数还是只执行一次就行。

举个例子,像dom的拖拽,如果用消抖的话,就会出现卡顿的感觉,因为只在停止的时候执行了一次,这个时候就应该用节流,在一定时间内多次执行,会流畅很多。

但是,如果是输入联想这种,我要输入“谁是世界上最帅的人?”,多次执行的话,可能当我输到最的时候,就去搜索,结果搜出来一堆“谁是世界上最笨”,“谁是世界上最胖”之类的不必要搜索,只需要在输入完成后进行搜索,消抖当时最合适啦。

实现

明白了定义与场景,让我们 脱下裤子 撸起袖子来造一个。

先看看名家手笔

underscore的实现

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  _.debounce = function(func, wait, immediate) {
    var timeout, result;

    var later = function(context, args) {
      timeout = null;
      if (args) result = func.apply(context, args);
    };

    var debounced = restArgs(function(args) {
      if (timeout) clearTimeout(timeout);
      if (immediate) {
        var callNow = !timeout;
        timeout = setTimeout(later, wait);
        if (callNow) result = func.apply(this, args);
      } else {
        timeout = _.delay(later, wait, this, args);
      }

      return result;
    });

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

    return debounced;
  };
  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time. Normally, the throttled function will run
  // as much as it can, without ever going more than once per `wait` duration;
  // but if you‘d like to disable the execution on the leading edge, pass
  // `{leading: false}`. To disable execution on the trailing edge, ditto.
  _.throttle = function(func, wait, options) {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {};

    var later = function() {
      previous = options.leading === false ? 0 : _.now();
      timeout = null;
      result = func.apply(context, args);
      if (!timeout) context = args = null; //显示地释放内存,防止内存泄漏
    };

    var throttled = function() {
      var now = _.now();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0 || remaining > wait) {
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        previous = now;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };

    throttled.cancel = function() {
      clearTimeout(timeout);
      previous = 0;
      timeout = context = args = null;
    };

    return throttled;
  };

实现了更灵活的option去控制是否立即执行,是否劫数是在执行以及增加cancel的控制逻辑。本着大道至简的精神(其实是懒),我们来改一个精简版只实现基本业务。

吐槽

红宝书上给的节流例子,嗯。。。怎么说呢。。。 是非常棒的消抖的实现,谢谢!!!!!

时间: 2024-10-22 19:05:32

js 消抖(debounce)与节流(throttle)的相关文章

js 函数的防抖(debounce)与节流(throttle)

原文:函数防抖和节流: 序言: 我们在平时开发的时候,会有很多场景会频繁触发事件,比如说搜索框实时发请求,onmousemove, resize, onscroll等等,有些时候,我们并不能或者不想频繁触发事件,咋办呢?这时候就应该用到函数防抖和函数节流了! 准备材料: <div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-col

防抖(Debounce)与节流( throttle)区别

throttle的作用是,预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新的时间周期.debounce的作用是,当调用动作触发一段时间后,才会执行该动作,若在这段时间间隔内又调用此动作则将重新计算时间间隔.debounce:把触发非常频繁的事件合并成一次执行.throttle:设置一个阀值,在阀值内,把触发的事件合并成一次执行:当到达阀值,必定执行一次事件. lodash.js中有两者很好的函数封装调用:_.throttle与_.debounce 当然也可以自

防抖(debounce)和节流(throttle)

防抖(debounce) 当调用动作触发一段时间后,才会执行该动作,若在这段时间间隔内又调用此动作则将重新计算时间间隔. function debounce(method, timeout, context) { return function() { var args = arguments clearTimeout(method.timer) method.timer = setTimeout(() => { method.apply(context, args) }, timeout) }

JavaScript 高级系列之节流 [throttle] 与防抖 [debounce]

一.概念 这两个东西都是为了项目优化而出现的,官方是没有具体定义的,他们的出现主要是为了解决一些短时间内连续执行的事件带来性能上的不佳和内存的消耗巨大等问题:像这类事件一般像 scroll keyup mousemove resize等等,短时间内不断的触发,在性能上消耗是非常大的,尤其是一些改变DOM结构的操作: 节流[throttle]与防抖[debounce]非常相似,都是让上述这类事件在规定的事件从不断的去触发更改成为规定的时间内触发多少次: 节流[throttle] 节流通俗来解释就比

jQueryAjax模拟按键消抖(可设置抖动延迟时间)

在硬件中,按键等都会有抖动现象,如何消除抖动,不重复触发事件呢,这就要用到消抖机制了. 这是我用jQuery模拟硬件消抖原理,额,可能是吧...又不对的地方,希望有高手指点指点. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验二:按键模块① - 消抖

实验二:按键模块① - 消抖 按键消抖实验可谓是经典中的经典,按键消抖实验虽曾在<建模篇>出现过,而且还惹来一堆麻烦.事实上,笔者这是在刁难各位同学,好让对方的惯性思维短路一下,但是惨遭口水攻击 ... 面对它,笔者宛如被甩的男人,对它又爱又恨.不管怎么样,如今 I'll be back,笔者再也不会重复一样的悲剧. 按键消抖说傻不傻说难不难.所谓傻,它因为原理不仅简单(就是延迟几下下而已),而且顺序语言(C语言)也有无数不尽的例子.所谓难,那是因为人们很难从单片机的思维跳出来 ... 此外,

【黑金教程笔记之005】【建模篇】【Lab 04 消抖模块之二】—笔记

实验四和实验三的区别在于输出.实验三是检测到由高到低的电平变化时就拉高输出,检测到由低到高的电平变化时就拉低输出.而实验四检测到由高到低的电平变化时产生一个100ms的高脉冲.当检测到由低到高的电平变化时,只有消抖操作. 模块: 1 /*********************************************************** 2 module name: detect_module.v 3 function: detect pin's level change 4 5

按键消抖之终极解决方案

1.按键消抖的原理 图1.按键抖动示意图 我们平常所用的按键为机械弹性开关,由于触点的弹性作用,按键在闭合时不会马上稳定的接通,而是有一段时间的抖动,在断开时也不会立即断开.抖动时间由按键的机械特性所决定,一般为5ms~10ms.所以我们在做按键检测时都要加一个消抖的过程. 按键消抖主要有两种方案: 一是延时重采样:二是持续采样. 从理论上来说,延时(如10ms)重采样的准确率肯定低于持续采样. 2.按键消抖的方法 (1)延时重采样 延时重采样的意思是,当第一次检测到键值由'1'变为'0'时,再

20150220【改进定时器】IMX257实现GPIO-IRQ定时器消抖驱动程序

[改进定时器]IMX257实现GPIO-IRQ定时器消抖驱动程序 2015-02-20 李海沿 前面我们的GPIO-IRQ按键的驱动程序实现了中断,阻塞,信号量,poll查询等功能,具体请进博客http://www.cnblogs.com/lihaiyan/ 本文,我们还是在前面的按键驱动程序的基础上,引入定时器,来消除抖动. 一.内核定时器详解 1.timer_list结构体 在/include/linux/timer.h中. struct timer_list { struct list_h