函数防抖(debounce)的实现
What is 防抖?
在事件触发n秒后再执行回调,如果在这n秒期间又被触发,则重新记时,也就是说在n秒之内只执行最后一次触发
执行过程
- 当事件触发时,相应的函数不会立即触发,而是会等待一定的时间
- 当事件密集触发时,函数的触发将会频繁重置延迟
- 只有延迟时间内再无任何事件触发,才会执行真正的响应函数
a426833e5d485957c71ee7c5a7870856
应用场景
- 输入框中频繁输入内容,搜索或提交信息
- 频繁点击按钮,触发某个事件
- 浏览器监听滚动事件完成某些操作
- 用户缩放浏览器的resize事件
功能实现
基础实现
function debounce(func, delay) {
//存储上一次触发的timer
let timer = 0;
return function (...args) {
//清除上一次触发的timer
timer ? clearTimeout(timer) : '';
timer = setTimeout(() => {
//绑定调用该函数上下文的this
func.apply(this,args);
}, delay);
};
}
简易版实现了最基本的防抖函数
封装立即执行功能
function debounce(func, delay, immediate = false) {
//存储上一次触发的timer
let timer = 0;
//
let invoke = false;
return function (...args) {
//清除上一次触发的timer
timer ? clearTimeout(timer) : '';
//在触发延迟回调前只执行一次
if (immediate && !invoke) {
invoke = true;
func.apply(this, args);
} else {
timer = setTimeout(() => {
//触发回调后 再次初始化
invoke = false;
//绑定调用该函数上下文的this
func.apply(this, args);
}, delay);
}
};
}
封装取消功能
function debounce(func, delay, immediate = false) {
//存储上一次触发的timer
let timer = null;
let invoke = false;
return function _debounce(...args) {
//清除上一次触发的timer
timer ? clearTimeout(timer) : '';
//在触发延迟回调前只执行一次
if (immediate && !invoke) {
invoke = true;
func.apply(this, args);
} else {
timer = setTimeout(() => {
//触发回调后 再次初始化
invoke = false;
//绑定调用该函数上下文的this
func.apply(this, args);
}, delay);
}
};
//封装取消功能
_debounce.cancel = function () {
timer ? clearTimeout(timer) : '';
timer = null;
invoke = false;
};
}
获取防抖函数返回值
- 使用Promise
function debounce(func, delay, immediate = false) {
//存储上一次触发的timer
let timer = null;
let invoke = false;
return function _debounce(...args) {
return new Promise((resolve, reject) => {
//清除上一次触发的timer
timer ? clearTimeout(timer) : '';
//在触发延迟回调前只执行一次
if (immediate && !invoke) {
invoke = true;
const result = func.apply(this, args);
//使用resolve把返回值抛出
resolve(result);
} else {
timer = setTimeout(() => {
//触发回调后 再次初始化
invoke = false;
//绑定调用该函数上下文的this
const result = func.apply(this, args);
resolve(result);
}, delay);
}
});
};
_debounce.cancel = function () {
timer ? clearTimeout(timer) : '';
timer = null;
invoke = false;
};
}
- 使用回调函数参数callback
function debounce(func, delay, immediate = false, callback) {
//存储上一次触发的timer
let timer = null;
//
let invoke = false;
return function _debounce(...args) {
//清除上一次触发的timer
timer ? clearTimeout(timer) : '';
//在触发延迟回调前只执行一次
if (immediate && !invoke) {
invoke = true;
const result = func.apply(this, args);
//利用回调函数把返回值抛出
if (callback) callback(result);
} else {
timer = setTimeout(() => {
//触发回调后 再次初始化
invoke = false;
//绑定调用该函数上下文的this
const result = func.apply(this, args);
if (callback) callback(result);
}, delay);
}
};
_debounce.cancel = function () {
timer ? clearTimeout(timer) : '';
timer = null;
invoke = false;
};
}