Underscore.js 是一个非常强大的JS库,今天针对场景的函数防抖和函数节流做一个总结。
前言
防抖(Debounce)和节流(throttle)都是用来控制某个函数在一定时间内执行多少次的技巧,两者相似而又不同。
应用场景
防抖场景
连续的事件,只需触发一次回调的场景有:
1.搜索框搜索输入。只需用户最后一次输入完,再发送请求;
2.手机号、邮箱验证输入检测;
3.窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流场景
间隔一段时间执行一次回调的场景有:
1.滚动加载,加载更多或滚到底部监听;
2.谷歌搜索框,搜索联想功能;
3.高频点击提交,表单重复提交。
函数防抖
如果在频繁的事件回调中做复杂计算,很有可能导致页面卡顿,不如将多次计算合并为一次计算,只在一个精确点做操作。
类似表单提交or登陆的业务操作,包括注册框的正则验证,如果一个事件被频繁触发多次,并且触发的时间间隔过短,则防抖函数可以使得对应的事件处理函数只执行一次,减少验证时间和页面过度请求响应
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
|
_.debounce = function(func, wait, immediate) { var timeout, args, context, timestamp, result;
var later = function() { var last = _.now() - timestamp;
if (last < wait && last > 0) { timeout = setTimeout(later, wait - last); } else { timeout = null; if (!immediate) { result = func.apply(context, args); if (!timeout) context = args = null; } } };
return function() { context = this; args = arguments; timestamp = _.now(); var callNow = immediate && !timeout; if (!timeout) timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); context = args = null; }
return result; }; };
|
整体函数实现的不难,总结一下。
对于按钮防点击来说的实现:一旦我开始一个定时器,只要我定时器还在,不管你怎么点击都不会执行回调函数。一旦定时器结束并设置为 null,就可以再次点击了。
对于延时执行函数来说的实现:每次调用防抖动函数都会判断本次调用和之前的时间间隔,如果小于需要的时间间隔,就会重新创建一个定时器,并且定时器的延时为设定时间减去之前的时间间隔。一旦时间到了,就会执行相应的回调函数。
函数节流
防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
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
|
_.throttle = function(func, wait, options) { var context, args, result; var timeout = null; 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; }; return 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) { 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; }; };
|
异同
简单来说:
防抖:把触发非常频繁的事件(比如按键)合并成一次执行。
节流:保证每 X 毫秒恒定的执行次数,间断执行。
相同点:
都可以通过使用 setTimeout 实现。
目的都是,降低回调执行频率。节省计算资源。
不同点:
函数防抖,在一段连续操作结束后,处理回调,利用 clearTimeout 和 setTimeout 实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。
函数防抖关注一定时间连续触发,只在最后执行一次,而函数节流侧重于一段时间内只执行一次。
用法
_.throttle 使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function log( event ) { console.log( $(window).scrollTop(), event.timeStamp ); };
$(window).scroll( log );
$(window).scroll( _.throttle( log, 250 ) ); _.debounce 使用示例 function ajax_lookup( event ) { };
$('input:text').keyup( ajax_lookup );
$('input:text').keyup( _.debounce( ajax_lookup, 250 ) );
|
参考文献
nderscore.js 备注:是一个很精干的库,压缩后只有5.2KB。它提供了几十种函数式编程的方法,弥补了标准库的不足,大大方便了JavaScript的编程。防抖和节流也在其中,还有一些好用的兼容工具。
作者:程序员思语
链接:https://juejin.cn/post/6978664839610630181
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。