debounce防抖
防止抖动(强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次)
比如你在某个2s时间段内连续触发了mousemove,浏览器可能会触发几百个相关事件,不适用防抖的话,会对用户体验造成很大的影响
实现思路
debounce 返回了一个闭包,这个闭包依然会被连续频繁地调用,但是在闭包内部,却限制了原始函数 fn 的执行,强制 fn 只在连续操作停止后只执行一次。
/**
* @param fn (function ) 实际要执行的函数
* @param delay(number) 延迟时间,也成阈值 单位为毫秒(ms)
*
* return (function) 返回了一个防抖之后的函数
*
*/
function _debounce(fn, delay) {
//设置定时器,用来执行settimeout
var timer;
// 返回一个函数,这个函数会在延迟时间delay(ms)之后执行
if (typeof fn != "function" || typeof delay != 'number') {
// alert(fn);
return;
}
return function() {
// 保存函数调用时的上下文和参数,传递给 fn
var _this = this
var args = arguments
// 每次这个返回的函数被调用,就清除定时器,以保证不执行 fn
clearTimeout(timer)
// 当返回的函数被最后一次调用后(也就是用户停止了某个连续的操作),
// 再过 delay 毫秒就执行 fn
timer = setTimeout(function() {
fn.apply(_this, args)
}, delay)
}
}
以mousemove 为例,我们看下这个函数的使用方式
<script>
var temp = document.getElementById('mycarousel'),
lis = temp.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
lis[i].onmousemove = _debounce(function(e) {
//触发
console.log(1)
}, 2000)
}
</script>
使用前
在输入框实现实时检索的场景中,通过input的change事件实时监测用户输入数据之后向服务器发送ajax请求。但在浏览器中的input框中,即使是用户正常的输入速度,事件被处罚的频率也是很高的,以这种高频率发送请求实在浪费资源,增加服务器的压力。
而在这是debounce 就派上用场了,在用户暂停输入一会儿之后,在发送请求。
input.addEventListener('onchange', _debounce(function(e) {
// 发送 ajax 请求
console.log(1)
}, 100), false);
throttle(节流)
持续触发事件时,throttle 会合并一定时间内的事件,并在该时间结束时真正去触发一次事件(固定函数执行的速率)
实现思路
相比 debounce,无非是多了一个时间间隔的判断,其他的逻辑基本一致。
/**
*
* @param fn {Function} 实际要执行的函数
* @param delay {Number} 执行间隔,单位是毫秒(ms)
*
* @return {Function} 返回一个“节流”函数
*/
function throttle(fn, delay) {
// 记录上次执行的时间
var last
// 定时器
var timer
// 默认间隔为 250ms
delay || (delay = 250)
// 返回的函数,每过 delay 毫秒就执行一次 fn 函数
return function() {
// 保存函数调用时的上下文和参数,传递给 fn
var context = this
var args = arguments
var now = +new Date()
// 如果距离上次执行 fn 函数的时间小于 delay,那么就放弃
// 执行 fn,并重新计时
if (last && now < last + delay) {
clearTimeout(timer)
// 保证在当前时间区间结束后,再执行一次 fn
timer = setTimeout(function() {
last = now
fn.apply(context, args)
}, delay)
// 在时间区间的最开始和到达指定间隔的时候执行一次 fn
} else {
last = now
fn.apply(context, args)
}
}
}
使用场景
throttle 常用的场景是限制 resize 和 scroll 的触发频率。以 scroll 为例
window.onscroll = _throttle(function(e) {
// 代码
console.log(1);
}, 250)
使用后
使用前
总结
debounce 强制函数在某段时间内只执行一次,throttle 强制函数以固定的速率执行。在处理一些高频率触发的 DOM 事件的时候,它们都能极大提高用户体验。