debounce是啥?
debounce一般被称为防抖动函数,核心目的在于减少函数被触发的频率,从而提高性能。
使用场景
- 减少resize、mousemove、 scroll等会频繁触发的事件执行次数。比如说我可以通过debounce做到resize结束后100ms才触发事件(因为我们可能不想resize事件被频繁触发,只需要窗口调整结束后再触发即可)
- 减少ajax请求次数。比如说现在有个需求,要求实现一个用户输入信息的同时从数据库查询相关信息并在前台进行展示,那么很显然,如果直接绑定input事件的话在用户输入的过程中此事件会频繁触发从而导致在短时间内发送多次ajax,一方面会影响性能,另一方面可能会导致用户都输入4个查询关键字了第一次的查询才刚返回,这就会导致查询结果和用户输入不一致的情况,用户体验不好。这种情况其实也可以用debounce来加以解决,如果用户一直在输入就不触发ajax请求,等用户停止输入100ms后立即发送ajax请求。
总之,debounce可以用来控制某个函数被触发的频率,从而提高性能和用户体验
不同的debounce实现
若干时间后触发(事件连续发生时不触发,等到事件发生结束后若干时间才触发操作,比如说等用户调整窗口大小结束后200ms再打印日志)
function debounce(func, wait) {
var timeout=null;
return function () {
var context = this;
var args = arguments;
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(function () {
func.apply(context, args);
clearTimeout(timeout);
timeout=null;
}, wait || 500);
}
}
// 用户每次停止调整窗口大小200ms后打印日志
window.onresize=debounce(function(){
console.log('hello world');
},200);
复制代码
立即触发(事件首次发生时触发,后续连续发生的话不触发事件)
function immediate(func, wait) {
var flag = true;
var timeout = null;
return function () {
if (flag) {
flag = false;
return func.apply(this, arguments);
}
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(function () {
flag = true;
}, wait);
}
};
// 用户开始调整窗口大小时记录日志,后续连续触发的话不记录日志,隔一段时间后首次触发再次记录日志
window.onresize = immediate(function () {
console.log('hello world');
}, 200);
复制代码
将延期执行和立即执行合并下(其实就是给debounce函数加个isImmediate参数,有参数的话就在动作发生后立即执行,否则就在动作连续执行后若干时间再执行)
function debounce(func, wait, isImmediate) {
if (isImmediate) {
return immediate(func, wait);
} else {
return delayDebounce(func,wait);
}
}
function immediate(func, wait) {
var flag = true;
var timeout = null;
return function () {
if (flag) {
flag = false;
return func.apply(this, arguments);
}
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(function () {
flag = true;
}, wait);
}
};
function delayDebounce(func, wait) {
var timeout = null;
return function () {
var context = this;
var args = arguments;
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(function () {
func.apply(context, args);
clearTimeout(timeout);
timeout = null;
}, wait || 500);
}
}
// 用户调整窗口后立即执行
window.onresize = debounce(function () {
console.log('hello world');
}, 200, true);
// 用户调整窗口结束若干时间后执行
window.onresize = debounce(function () {
console.log('hello world');
}, 200);
复制代码
结语
性能优化应该是每个热爱技术的宝宝绕不过的坎,所以,既然绕不过,那就在性能调优的深海里浪里个浪好啦,O(∩_∩)O哈哈~