防抖(debounce) 和 节流(throttling)
防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 在给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)相关推荐
- 防抖(debounce) 和 节流(throttling)的封装使用-最终发布npm
函数的防抖节流 前言 防抖函数 防抖函数(雏形) 防抖函数1.0(使用了闭包) 防抖函数2.0(此版本开始才称得上是封装) 防抖函数3.0(希望第一次点击就立即触发) 防抖函数4.0(解决this指向 ...
- 防抖debounce和节流throttle
大纲 一.出现缘由 二.什么是防抖debounce和节流throttle 三.应用场景 3.1防抖 3.2节流 一.出现缘由 前端开发中,有一部分用户行为会频繁触发事件,而对于DOM操作,资源加载等耗 ...
- 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用
函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 文章目录 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 1. 为什么要防抖节流 1.1 ...
- 探究防抖(debounce)和节流(throttle)
本文来自我的博客,欢迎大家去GitHub上star我的博客 本文从防抖和节流出发,分析它们的特性,并拓展一种特殊的节流方式requestAnimationFrame,最后对lodash中的deboun ...
- Java版的防抖(debounce)和节流(throttle)
概念 防抖(debounce) 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时 节流(throttle) 当持续触发事件时, ...
- 函数防抖(debounce)和节流(throttle)以及lodash的debounce源码赏析
函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听.比如scroll resize等事件,这些事件在某些场景触发非常频繁. 比如,实现一个原生的拖拽功能(不能用 H5 Drag& ...
- 手写防抖(debounce)和节流(throttle)
目录 测试代码 防抖(debounce) 基本功能实现 添加参数及this指向功能 第一次立即执行功能 取消功能 节流(throttle) 基本功能实现 增加this执向 最后一次在禁止时间段内是否执 ...
- JS高级 之 防抖 debounce - throttle 节流
目录 一.防抖 debounce 1. 概念 2. 应用场景 3. 使用 underscore 实现防抖 01 - 代码 02 - 效果 4. 实现 01 - 基本实现 代码 效果 02 - 优化 = ...
- 防抖(debounce)和节流(throttle)
针对一些会频繁触发的事件如scroll.resize,如果正常绑定事件处理函数的话,有可能在很短的时间内多次连续触发事件,十分影响性能.防抖和节流就是针对响应跟不上触发频率这类问题的两种解决方案 因此 ...
最新文章
- SQL与NoSQL区别-存储方式
- laravel 模型查找数据
- python练习---模拟sql
- ubuntu下安装minicom
- 删除用户的命令是什么mysql_mysql新添加用户与删除用户具体操作命令_MySQL
- (JAVA)List
- 不降的数字(51Nod-2499)
- 力扣-二叉树的前序遍历
- GoldenGate应用拓扑结构(三)
- 如何取到两个日期中的每一天,并且打印出来
- BoolToVisibilityConverter In WPF
- 清理300多台MySQL数据库的过期binlog日志
- (转)Linux 系统性能分析工具图解读(一、二)
- Codeforces Round #390 (Div. 2) A. Lesha and array splitting
- 简易c语言编程软件,c语言开发工具下载
- 如何从12306网站下载自己喜欢的手机铃声
- LTO磁带机清洁准则
- 偏最小二乘(Partial Least Squares,PLS)原理及模型建立
- Kubernetes-Host网络模式,指定Pod 物理机IP
- altium summer 9导入orcad dsn文件的方法
热门文章
- python推箱子小游戏_小伙利用Python自制一个推箱子小游戏!
- 以 Animated Drawings APP 为例,用 TorchServe 进行模型调优
- 一百元打造属于自己的健身房,还去什么健身房?
- CSS中文字体的英文名称(simhei, simsun)
- Phase-Functioned Neural Networks for Character Control论文翻译(用于角色控制的相位功能神经网络)
- C语言求1000后面有多少个0,1到1000的阶乘 求1000阶乘的结果末尾有多少个0
- 执行HBase建表操作,每次创建表HRegionServer都会挂掉,而 HMaster还在!RetriesExhaustedException: Can't get the locations
- ElastIcSearch分词器
- 【2022集创赛】安谋科技杯三等奖:基于ARM处理器的无线SoC设计
- 多层嵌套可迭代列表的剥皮函数