debounce 与 throttle 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。
使用场景:比如绑定响应鼠标移动、窗口大小调整、滚屏等事件时,绑定的函数触发的频率会很频繁。若稍处理函数微复杂,需要较多的运算执行时间和资源,往往会出现延迟,甚至导致假死或者卡顿感。为了优化性能,这时就很有必要使用debounce或throttle了。
由于debounce与throttle两个函数的作用相同,且调用方法和参数都相同,这让我们很容易弄混。今天就来谈谈debounce和throttle的用法与差异。
下面先看看lodash中的.debounce()与.throttle()。
_.debounce(func, [wait=0], [options={}]);
_.throttle(func, [wait=0], [options={}]);
1. debounce
语法:
_.debounce(func, [wait=0], [options={}])
debounce函数通常称为防抖动函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 fn 方法
适用场景:
按钮提交:防止多次提交,只执行最后一次提交
搜索框联想场景:防止联想发送请求,只发送最后一次输入
简单实现
function debounce(fn, wait, options) {
wait = wait || 0;
var timerId;
function debounced() {
if (timerId) {
clearTimeout(timerId);
timerId = null;
}
timerId = setTimeout(function() {
fn();
}, wait);
}
return debounced;
}
当事件被执行时,并不会立刻执行fn,而是等待一定时间(wait)后才会执行。如果wait过后,函数没有再次被执行,就会处理最后一个fn。
2. Throttle
语法:
_.throttle(func, [wait=0], [options={}])
throttle:规定在单位时间内,只能触发一次函数,如果这个单位时间触发多次,只有一次生效
使用场景:
拖拽场景
缩放:监控浏览器resize
简单实现
function throttle(fn, wait, options) {
wait = wait || 0;
var timerId, lastTime = 0;
function throttled() {
var currentTime = new Date();
if (currentTime >= lastTime + wait) {
fn();
lastTime = currentTime;
} else {
if (timerId) {
clearTimeout(timerId);
timerId = null;
}
timerId = setTimeout(function() {
fn();
}, wait);
}
}
return throttled;
}
在上面的代码中,我们会记录每次函数被实际调用的时间,如果下次调用时,还没到达阀值,就会继续等待,直到到达阀值,就会调用最后一次函数。
const debounce300LoadMore = debounce(300, false, this.getMore);
window.addEventListener('scroll', debounce300LoadMore, {
passive: false
});
两者区别:
节流不管事件触发多频繁保证在一定时间内一定会执行一次函数。防抖是只在最后一次事件触发后才会执行一次函数
问题: 多个tab标签,如何保证每次点击tab加载的都是对应的准确数据