防抖與節(jié)流
1. 什么是防抖
對于短時間內(nèi)連續(xù)觸發(fā)的函數(shù)囊嘉,在函數(shù)最后一次調(diào)用時刻的 wait 毫秒之后執(zhí)行孔庭。如:監(jiān)聽搜索框的連續(xù)輸入知举,監(jiān)聽屏幕的滾動事件等寇壳。
基本的防抖
const debounce = (fn, wait = 500) => {
let timeout = null;
return function () {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, wait);
};
};
進(jìn)階的防抖
對于一些按鈕事件瓷耙,為防止用戶多次點擊朱躺,需要立即執(zhí)行一次,在函數(shù)最后一次調(diào)用的 wait 毫秒后搁痛,再次點擊才能執(zhí)行长搀。添加立即執(zhí)行參數(shù)(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);
}
};
};
最終優(yōu)化版
/**
* 防抖函數(shù)最終優(yōu)化版
* immediate = false: 在函數(shù)最后一次調(diào)用的 wait 毫秒之后執(zhí)行
* immediate = true: 立即執(zhí)行第一次,在最后一次調(diào)用的 wait 毫秒后鸡典,可再次點擊繼續(xù)觸發(fā)
* @param {function} fn 需要執(zhí)行的函數(shù)
* @param {number} wait 時間間隔
* @param {boolean} immediate 是否立即執(zhí)行
* @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. 什么是節(jié)流
像節(jié)流閥一樣的函數(shù)源请,當(dāng)重復(fù)調(diào)用函數(shù)的時候,至少每隔 wait 毫秒調(diào)用一次該函數(shù)彻况。對于想控制一些觸發(fā)頻率較高的事件有幫助谁尸。
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);
};
};
/**
* 節(jié)流函數(shù)最終優(yōu)化版
* immediate = false: 不會立即執(zhí)行,每隔 wait 毫秒后執(zhí)行一次纽甘。
* immediate = true: 立即執(zhí)行一次良蛮,后續(xù)每隔 wait 毫秒后執(zhí)行一次。
* @param {function} fn 需要執(zhí)行的函數(shù)
* @param {number} wait 時間間隔
* @param {boolean} immediate 是否立即執(zhí)行
* @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. 防抖節(jié)流函數(shù)合并版本
/**
* 防抖節(jié)流函數(shù)合并版本
* @param {function} fn 需要執(zhí)行的函數(shù)
* @param {number} wait 時間間隔
* @param {'debounce' | 'throttle'} type 防抖或節(jié)流
* @param {boolean} immediate 是否立即執(zhí)行
* @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);
};
};