防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 在给DOM绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件onmousemove, 滚动滚动条事件onscroll,窗口大小改变事件onresize,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。 在实时检查输入时,如果我们绑定onkeyup事件发请求去服务端检查,用户输入过程中,事件的触发频率也会很高,会导致大量的请求发出,响应速度会大大跟不上触发。

针对此类快速连续触发和不可控的高频触发问题,debounce 和 throttling 给出了两种解决策略;

debounce,去抖动。策略是当事件被触发时,设定一个周期延迟执行动作,若期间又被触发,则重新设定周期,直到周期结束,执行动作。 这是debounce的基本思想,在后期又扩展了前缘debounce,即执行动作在前,然后设定周期,周期内有事件被触发,不执行动作,且周期重新设定。

延迟debounce,示意图:

前缘debounce, 示意图

debounce的特点是当事件快速连续不断触发时,动作只会执行一次。 延迟debounce,是在周期结束时执行,前缘debounce,是在周期开始时执行。但当触发有间断,且间断大于我们设定的时间间隔时,动作就会有多次执行。

debounce 的实现:

版本1:  周期内有新事件触发,清除旧定时器,重置新定时器;这种方法,需要高频的创建定时器。

// 暴力版: 定时器期间,有新操作时,清空旧定时器,重设新定时器
var debounce = (fn, wait) => {let timer, timeStamp=0;let context, args;let run = ()=>{timer= setTimeout(()=>{fn.apply(context,args);},wait);}let clean = () => {clearTimeout(timer);}return function(){context=this;args=arguments;let now = (new Date()).getTime();if(now-timeStamp < wait){console.log('reset',now);clean();  // clear running timer run();    // reset new timer from current time}else{console.log('set',now);run();    // last timer alreay executed, set a new timer}timeStamp=now;}}

版本2: 周期内有新事件触发时,重置定时器开始时间撮,定时器执行时,判断开始时间撮,若开始时间撮被推后,重新设定延时定时器。

/ 优化版: 定时器执行时,判断start time 是否向后推迟了,若是,设置延迟定时器
var debounce = (fn, wait) => {let timer, startTimeStamp=0;let context, args;let run = (timerInterval)=>{timer= setTimeout(()=>{let now = (new Date()).getTime();let interval=now-startTimeStampif(interval<timerInterval){ // the timer start time has been reset, so the interval is less than timerIntervalconsole.log('debounce reset',timerInterval-interval);startTimeStamp=now;run(wait-interval);  // reset timer for left time }else{fn.apply(context,args);clearTimeout(timer);timer=null;}},timerInterval);}return function(){context=this;args=arguments;let now = (new Date()).getTime();startTimeStamp=now;if(!timer){console.log('debounce set',wait);run(wait);    // last timer alreay executed, set a new timer}}}

版本3: 在版本2基础上增加是否立即执行选项:

// 增加前缘触发功能
var debounce = (fn, wait, immediate=false) => {let timer, startTimeStamp=0;let context, args;let run = (timerInterval)=>{timer= setTimeout(()=>{let now = (new Date()).getTime();let interval=now-startTimeStampif(interval<timerInterval){ // the timer start time has been reset,so the interval is less than timerIntervalconsole.log('debounce reset',timerInterval-interval);startTimeStamp=now;run(wait-interval);  // reset timer for left time }else{if(!immediate){fn.apply(context,args);}clearTimeout(timer);timer=null;}},timerInterval);}return function(){context=this;args=arguments;let now = (new Date()).getTime();startTimeStamp=now; // set timer start timeif(!timer){console.log('debounce set',wait);if(immediate) {fn.apply(context,args);}run(wait);    // last timer alreay executed, set a new timer}}}

throttling,节流的策略是,固定周期内,只执行一次动作,若有新事件触发,不执行。周期结束后,又有事件触发,开始新的周期。 节流策略也分前缘和延迟两种。与debounce类似,延迟是指 周期结束后执行动作,前缘是指执行动作后再开始周期。

延迟throttling示意图:

前缘throttling 示意图:

throttling的特点在连续高频触发事件时,动作会被定期执行,响应平滑。

throttling 的实现:

版本1: 简单版

简单版: 定时器期间,只执行最后一次操作
var throttling = (fn, wait) => {let timer;let context, args;let run = () => {timer=setTimeout(()=>{fn.apply(context,args);clearTimeout(timer);timer=null;},wait);}return function () {context=this;args=arguments;if(!timer){console.log("throttle, set");run();}else{console.log("throttle, ignore");}}}

版本2: 增加前缘选项:(考虑情况较简单,复杂情况可参考underscope 的_.throttle)

/// 增加前缘
var throttling = (fn, wait, immediate) => {let timer, timeStamp=0;let context, args;let run = () => {timer=setTimeout(()=>{if(!immediate){fn.apply(context,args);}clearTimeout(timer);timer=null;},wait);}return function () {context=this;args=arguments;if(!timer){console.log("throttle, set");if(immediate){fn.apply(context,args);}run();}else{console.log("throttle, ignore");}}}

debounce和throttling 各有特点,在不同 的场景要根据需求合理的选择策略。如果事件触发是高频但是有停顿时,可以选择debounce; 在事件连续不断高频触发时,只能选择throttling,因为debounce可能会导致动作只被执行一次,界面出现跳跃。

防抖(debounce) 和 节流(throttling)相关推荐

  1. 防抖(debounce) 和 节流(throttling)的封装使用-最终发布npm

    函数的防抖节流 前言 防抖函数 防抖函数(雏形) 防抖函数1.0(使用了闭包) 防抖函数2.0(此版本开始才称得上是封装) 防抖函数3.0(希望第一次点击就立即触发) 防抖函数4.0(解决this指向 ...

  2. 防抖debounce和节流throttle

    大纲 一.出现缘由 二.什么是防抖debounce和节流throttle 三.应用场景 3.1防抖 3.2节流 一.出现缘由 前端开发中,有一部分用户行为会频繁触发事件,而对于DOM操作,资源加载等耗 ...

  3. 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用

    函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 文章目录 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 1. 为什么要防抖节流 1.1 ...

  4. 探究防抖(debounce)和节流(throttle)

    本文来自我的博客,欢迎大家去GitHub上star我的博客 本文从防抖和节流出发,分析它们的特性,并拓展一种特殊的节流方式requestAnimationFrame,最后对lodash中的deboun ...

  5. Java版的防抖(debounce)和节流(throttle)

    概念 防抖(debounce) 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时 节流(throttle) 当持续触发事件时, ...

  6. 函数防抖(debounce)和节流(throttle)以及lodash的debounce源码赏析

    函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听.比如scroll resize等事件,这些事件在某些场景触发非常频繁. 比如,实现一个原生的拖拽功能(不能用 H5 Drag& ...

  7. 手写防抖(debounce)和节流(throttle)

    目录 测试代码 防抖(debounce) 基本功能实现 添加参数及this指向功能 第一次立即执行功能 取消功能 节流(throttle) 基本功能实现 增加this执向 最后一次在禁止时间段内是否执 ...

  8. JS高级 之 防抖 debounce - throttle 节流

    目录 一.防抖 debounce 1. 概念 2. 应用场景 3. 使用 underscore 实现防抖 01 - 代码 02 - 效果 4. 实现 01 - 基本实现 代码 效果 02 - 优化 = ...

  9. 防抖(debounce)和节流(throttle)

    针对一些会频繁触发的事件如scroll.resize,如果正常绑定事件处理函数的话,有可能在很短的时间内多次连续触发事件,十分影响性能.防抖和节流就是针对响应跟不上触发频率这类问题的两种解决方案 因此 ...

最新文章

  1. SQL与NoSQL区别-存储方式
  2. laravel 模型查找数据
  3. python练习---模拟sql
  4. ubuntu下安装minicom
  5. 删除用户的命令是什么mysql_mysql新添加用户与删除用户具体操作命令_MySQL
  6. (JAVA)List
  7. 不降的数字(51Nod-2499)
  8. 力扣-二叉树的前序遍历
  9. GoldenGate应用拓扑结构(三)
  10. 如何取到两个日期中的每一天,并且打印出来
  11. BoolToVisibilityConverter In WPF
  12. 清理300多台MySQL数据库的过期binlog日志
  13. (转)Linux 系统性能分析工具图解读(一、二)
  14. Codeforces Round #390 (Div. 2) A. Lesha and array splitting
  15. 简易c语言编程软件,c语言开发工具下载
  16. 如何从12306网站下载自己喜欢的手机铃声
  17. LTO磁带机清洁准则
  18. 偏最小二乘(Partial Least Squares,PLS)原理及模型建立
  19. Kubernetes-Host网络模式,指定Pod 物理机IP
  20. altium summer 9导入orcad dsn文件的方法

热门文章

  1. python推箱子小游戏_小伙利用Python自制一个推箱子小游戏!
  2. 以 Animated Drawings APP 为例,用 TorchServe 进行模型调优
  3. 一百元打造属于自己的健身房,还去什么健身房?
  4. CSS中文字体的英文名称(simhei, simsun)
  5. Phase-Functioned Neural Networks for Character Control论文翻译(用于角色控制的相位功能神经网络)
  6. C语言求1000后面有多少个0,1到1000的阶乘 求1000阶乘的结果末尾有多少个0
  7. 执行HBase建表操作,每次创建表HRegionServer都会挂掉,而 HMaster还在!RetriesExhaustedException: Can't get the locations
  8. ElastIcSearch分词器
  9. 【2022集创赛】安谋科技杯三等奖:基于ARM处理器的无线SoC设计
  10. 多层嵌套可迭代列表的剥皮函数