防抖(debounce)
所謂防抖,就是指觸發事件後 n 秒後才執行函式,如果在 n 秒內又觸發了事件,則會重新計算函式執行時間。
防抖型別分為
- 非立即執行版
- 立即執行版
- 合成版本 防抖
防抖應用場景
- 登入、發簡訊等按鈕避免使用者點選太快,以致於傳送了多次請求
- 調整瀏覽器視窗大小時,resize 次數過於頻繁,造成計算過多,此時需要一次到位
- 文字編輯器實時儲存,當無任何更改操作一秒後進行儲存
非立即執行版
非立即執行版的意思是觸發事件後函式不會立即執行,而是在 n 秒後執行,如果在 n 秒內又觸發了事件,則會重新計算函式執行時間。
/**
* @description:
* @param {*} func 觸發的事件
* @param {*} wait 多少時長才執行事件
* @return {*}
*/
function debounce(func, wait) {
let timeout;
return function(){
// 獲取當前作用域和引數
const context = this;
const args = [...arguments]
// 如果當前timeout 存在
// 清空定時器,再次等待wait時間過後再次執行事件
if(timeout) clearTimeout(timeout)
// 定時執行 傳遞進來的事件
timeout = setTimeout(()=>{
func.apply(context,args)
},wait)
}
}
立即執行版本
立即執行版的意思是觸發事件後函式會立即執行,然後 n 秒內不觸發事件才能繼續執行函式的效果。
function debounce(func,wait) {
let timeout;
return function () {
const context = this;
const args = [...arguments];
if (timeout) clearTimeout(timeout);
const callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
}
程式碼解析
當 執行
debounce
函式時, 第一次進來時,timeout
為false,所以callNow
的值 為true
,那麼它會立即執行func
函式,這時timeout
的值 為true
, 當timeout 值為true 時
, 會執行 清空定時器,此時 timeout 又為 false 了
, 這時callNow
又 為true
,再次執行func
函式。一直迴圈這樣的操作:
當
timeout
為false
時,會立刻執行func
函式。當
timeout
為true
時,它會執行clearTimeOut
,這時timeout
又為false
, 而callNow
=! timeout
, 就會立刻執行func
函式了。
合成版本 防抖
通過傳遞
Boolean
來決定執行哪種版本。
true
為立即執行版false
為非立即執行版本
debounce(func,1000,true)
/**
* @desc 函式防抖
* @param func 函式
* @param wait 延遲執行毫秒數
* @param immediate true 表立即執行,false 表非立即執行
*/
function debounce(func, wait, immediate) {
let timeout;
return function () {
const context = this;
const args = [...arguments];
if (timeout) clearTimeout(timeout);
if (immediate) {
const callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(() => {
func.apply(context, args)
}, wait);
}
}
}
節流
所謂節流,就是指連續觸發事件但是在 n 秒中只執行一次函式。 節流會稀釋函式的執行頻率。
節流有兩種實現:
- 時間戳版本
- 定時器版本
節流應用場景
scroll
事件,每隔一秒計算一次位置資訊等- 瀏覽器播放事件,每個一秒計算一次進度資訊等
input
輸入框在搜尋內容時,可以控制多少s 在執行請求,避免多次發起請求,節約效能。
時間戳版本
function throttle(func, wait) {
var previous = 0;
return function() {
let now = Date.now();
let context = this;
let args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
定時器版本
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
程式碼解析
當執行
throttle
函式時,timeout
預設為undefined
, 此時,! timeout
為true
時,執行 定時器,並且 將timeout
為 null,即為false
, 再次執行throttle
函式時,!timeout
又為true
,再次執行定時器。**通過
timeout
的狀態來達到節流的控制 **
總結
防抖: 觸發事件後,一定時間後再執行事件,可以
立即執行
也可以一定時間再執行
節流: 控制流量,在單位時間內只能請求一次,避免多次觸發事件,影響伺服器效能。
結語
❤️關注+點贊+收藏+評論+轉發❤️,原創不易,鼓勵筆者創作更好的文章
關注公眾號 前端自學社群,即可獲取更多前端高質量文章!
關注後回覆關鍵詞“加群”, 即可加入 “前端自學交流群”,共同學習進步。
關注後新增我微信拉你進技術交流群
歡迎關注公眾號,更多精彩文章只在公眾號推送