一、简化版本
1、防抖函数
function debounce(fun, wait, immediate) {
var timer = null
return function proxy() {
var self = this,
params = [].slice.call(arguments),
callNow = immediate && !timer
if (timer) clearTimeout(timer)
timer = setTimeout(function () {
clearTimeout(timer)
timer = null
!callNow && handle.apply(self, params)
}, wait)
if (callNow) handle.apply(self, params)
}
}
2、调用
var btn = document.getElementById('btn')
var handle = function () {
var xhr = new XMLHttpRequest
xhr.open('GET', '../code.txt')
xhr.onreadystatechange = function () {
}
xhr.send(null)
return 1111
}
btn.onclick = debounce(handle, 1000, true)
二、复杂版本
1、函数防抖定义
(1)设置一个WAIT时间,此时间是用户自己定义,多久内触发多次算是频繁触发
(2)函数防抖:在频繁触发的模式下,我们只识别一次「可以只识别第一次immediate=true,也可以识别最后一次」
2、在每个设置的时间的最后执行
我们只要设置一个定时器,然后wait时间之后执行这个需要执行的函数,如果在这个时间之内频繁的触发了这个函数,那么我们需要把之前的定时器干掉,重新设置定时器,直到是在我们设置的时间之内的最后执行函数即可(这个时间之内必须只执行最后一次,不能干扰);
3、在每个设置的时间的开始执行
我们只需要传入immediate这个字段,让其为true,这样的话,我们判读只要是timer是null的话,就可以让这个函数执行,然后timer设置为了一个定时器,这个定时器在wait秒之后变为null即可;
function debounce(func, wait, immediate) {
if (typeof func !== "function") throw new TypeError('func must be a function!');
if (typeof wait === "undefined") {
wait = 500;
immediate = false;
}
if (typeof wait === "boolean") {
immediate = wait;
wait = 500;
}
if (typeof wait !== "number") throw new TypeError('wait must be a number!');
if (typeof immediate !== "boolean") throw new TypeError('immediate must be a boolean!');
var timer = null
return function proxy() {
var self = this,
params = [].slice.call(arguments),
callNow = !timer && immediate;
if (timer) clearTimeout(timer);
timer = setTimeout(function () {
// 清除最后一次定时器
clearTimeout(timer);
timer = null;
// 符合执行的是最后一次「触发在结束边界」
!immediate && func.apply(self, params);
}, wait);
// 符合第一次立即执行「触发在开始的边界」
callNow && func.apply(self, params);
};
}
自己的分析:
为什么要使用闭包的机制呢 ? 因为绑定给事件的函数是一个立即执行函数,如果我们不返回一个函数,就会立即将这个函数执行,这样是不对的。
4、执行
const handle = function handle(ev) {
console.log(this, ev);
setTimeout(() => {
$.ajax({
url: './code.txt',
success(result) {
console.log(result);
}
});
}, 1000);
};
submit.onclick = debounce(handle, true);
// 用户疯狂点击,proxy函数会疯狂的执行,但是我们最后要执行的是handle,所以我们只需要在proxy执行多次的时候,基于一些列的判断处理,让handle只执行一次即可