防抖与节流
1. 什么是防抖
对于短时间内连续触发的函数,在函数最后一次调用时刻的 wait 毫秒之后执行。如:监听搜索框的连续输入,监听屏幕的滚动事件等。
基本的防抖
const debounce = (fn, wait = 500) => {
let timeout = null;
return function () {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, wait);
};
};
进阶的防抖
对于一些按钮事件,为防止用户多次点击,需要立即执行一次,在函数最后一次调用的 wait 毫秒后,再次点击才能执行。添加立即执行参数(immediate = true)
const debounce = (fn, wait = 500, immediate = false) => {
let timeout;
return function () {
if (immediate) {
if (!timeout) {
fn.apply(this, arguments);
} else {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
timeout = null;
}, wait);
} else {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
timeout = null;
fn.apply(this, arguments);
}, wait);
}
};
};
最终优化版
/**
* 防抖函数最终优化版
* immediate = false: 在函数最后一次调用的 wait 毫秒之后执行
* immediate = true: 立即执行第一次,在最后一次调用的 wait 毫秒后,可再次点击继续触发
* @param {function} fn 需要执行的函数
* @param {number} wait 时间间隔
* @param {boolean} immediate 是否立即执行
* @returns function
*/
const debounce = (fn, wait, immediate = false) => {
let timeout;
return function () {
if (timeout) {
clearTimeout(timeout);
} else if (immediate) {
fn.apply(this, arguments);
}
timeout = setTimeout(() => {
if (!immediate) {
fn.apply(this, arguments);
}
timeout = null;
}, wait);
};
};
2. 什么是节流
像节流阀一样的函数,当重复调用函数的时候,至少每隔 wait 毫秒调用一次该函数。对于想控制一些触发频率较高的事件有帮助。
const throttle = (fn, wait = 500) => {
let isRuning = false;
let timeout = null;
return function () {
if (isRuning) {
return;
}
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
isRuning = true;
timeout = setTimeout(() => {
fn.apply(this, arguments);
isRuning = false;
timeout = null;
}, wait);
};
};
/**
* 节流函数最终优化版
* immediate = false: 不会立即执行,每隔 wait 毫秒后执行一次。
* immediate = true: 立即执行一次,后续每隔 wait 毫秒后执行一次。
* @param {function} fn 需要执行的函数
* @param {number} wait 时间间隔
* @param {boolean} immediate 是否立即执行
* @returns function
*/
const throttle = (fn, wait = 500, immediate = false) => {
let isRuning = false;
let timeout = null;
return function () {
if (isRuning) {
return;
}
if (timeout) {
clearTimeout(timeout);
timeout = null;
} else if (immediate) {
fn.apply(this, arguments);
}
isRuning = true;
timeout = setTimeout(() => {
fn.apply(this, arguments);
immediate = false;
isRuning = false;
timeout = null;
}, wait);
};
};
3. 防抖节流函数合并版本
/**
* 防抖节流函数合并版本
* @param {function} fn 需要执行的函数
* @param {number} wait 时间间隔
* @param {'debounce' | 'throttle'} type 防抖或节流
* @param {boolean} immediate 是否立即执行
* @returns function
*/
const all = (fn, wait, type = "debounce", immediate = false) => {
let isRuning = false;
let timeout = null;
return function () {
if (isRuning && type === "throttle") {
return;
}
if (timeout) {
clearTimeout(timeout);
timeout = null;
} else if (immediate) {
fn.apply(this, arguments);
}
isRuning = true;
timeout = setTimeout(() => {
if (type === "throttle") {
fn.apply(this, arguments);
immediate = false;
} else {
if (!immediate) {
fn.apply(this, arguments);
}
}
isRuning = false;
timeout = null;
}, wait);
};
};