江蘇網(wǎng)站建設(shè)網(wǎng)絡(luò)公司百度愛采購官網(wǎng)
防抖說明
(1)防抖的目的:
當(dāng)多次執(zhí)行某一個(gè)動(dòng)作的時(shí)候,限制函數(shù)調(diào)用的次數(shù),節(jié)約資源。
(2)防抖的概念:
函數(shù)防抖(debounce):就是指觸發(fā)事件后,在 n 秒內(nèi)函數(shù)只能執(zhí)行一次,如果觸發(fā)事件后在 n 秒內(nèi)又觸發(fā)了事件,則會(huì)重新計(jì)算函數(shù)延執(zhí)行時(shí)間。
(3)防抖的應(yīng)用場(chǎng)景:
連續(xù)的事件,只需觸發(fā)一次回調(diào)的場(chǎng)景:
- 窗口大小Resize。只需窗口調(diào)整完成后,計(jì)算窗口大小。防止重復(fù)渲染
- scroll
- 鼠標(biāo)的mousemove ,mousehover事件?
- 重復(fù)的ajax調(diào)用(會(huì)造成網(wǎng)絡(luò)擁塞,增加服務(wù)器壓力)
- 登錄、發(fā)短信等按鈕避免用戶點(diǎn)擊太快,以致于發(fā)送了多次請(qǐng)求
- 對(duì)信息進(jìn)行驗(yàn)證
被頻繁觸發(fā)(短時(shí)間內(nèi)多次觸發(fā)),不做限制的話,有可能一秒之內(nèi)執(zhí)行幾十次、幾百次。
如果在這些函數(shù)內(nèi)部執(zhí)行了其他函數(shù),尤其是執(zhí)行了操作 DOM 的函數(shù)(瀏覽器操作 DOM 是很耗費(fèi)性能的),那不僅會(huì)浪費(fèi)計(jì)算機(jī)資源,還會(huì)降低程序運(yùn)行速度,甚至造成瀏覽器卡死、崩潰。這種問題顯然是致命的。
防抖實(shí)現(xiàn)(力扣題目2627. 函數(shù)防抖 - 力扣(LeetCode))
題目:
請(qǐng)你編寫一個(gè)函數(shù),接收參數(shù)為另一個(gè)函數(shù)和一個(gè)以毫秒為單位的時(shí)間?t
?,并返回該函數(shù)的?函數(shù)防抖?后的結(jié)果。
函數(shù)防抖?方法是一個(gè)函數(shù),它的執(zhí)行被延遲了?t
?毫秒,如果在這個(gè)時(shí)間窗口內(nèi)再次調(diào)用它,它的執(zhí)行將被取消。你編寫的防抖函數(shù)也應(yīng)該接收傳遞的參數(shù)。
例如,假設(shè)?t = 50ms
?,函數(shù)分別在?30ms
?、?60ms
?和?100ms
?時(shí)調(diào)用。前兩個(gè)函數(shù)調(diào)用將被取消,第三個(gè)函數(shù)調(diào)用將在?150ms
?執(zhí)行。如果改為?t = 35ms
?,則第一個(gè)調(diào)用將被取消,第二個(gè)調(diào)用將在?95ms
?執(zhí)行,第三個(gè)調(diào)用將在?135ms
?執(zhí)行。
?
上圖展示了了防抖函數(shù)是如何轉(zhuǎn)換事件的。其中,每個(gè)矩形表示 100ms,反彈時(shí)間為 400ms。每種顏色代表一組不同的輸入。
案例:
輸入: t = 50 calls = [{"t": 50, inputs: [1]},{"t": 75, inputs: [2]} ] 輸出:[{"t": 125, inputs: [2]}] 解釋: let start = Date.now(); function log(...inputs) { console.log([Date.now() - start, inputs ]) } const dlog = debounce(log, 50); setTimeout(() => dlog(1), 50); setTimeout(() => dlog(2), 75);第一次調(diào)用被第二次調(diào)用取消,因?yàn)榈诙握{(diào)用發(fā)生在 100ms 之前 第二次調(diào)用延遲 50ms,在 125ms 執(zhí)行。輸入為 (2)。
?
代碼實(shí)現(xiàn):?
var debounce = function(fn, t) {// 要執(zhí)行的函數(shù)(fn),延遲的時(shí)間(t)var time = null;return function(...args) {if(time){// 清除定時(shí)器clearTimeout(time);}time = setTimeout(()=>{fn(...args);},t)}
};
?
代碼說明:
- 函數(shù)防抖需要一個(gè)?setTimeout?來輔助實(shí)現(xiàn),setTimeout?延遲運(yùn)行需要執(zhí)行的代碼。
- 多次觸發(fā),使用?clearTimeout?取消了先前通過調(diào)用?setTimeout 建立的定時(shí)器,即清除之前的延遲記錄。重新計(jì)時(shí)。
- 若計(jì)時(shí)期間事件沒有被重新觸發(fā),等延遲時(shí)間計(jì)時(shí)完畢,則執(zhí)行目標(biāo)代碼。
防抖的 “立即執(zhí)行版” 和 “非立即執(zhí)行版”
?函數(shù)防抖其實(shí)是分為 “立即執(zhí)行版” 和 “立即執(zhí)行版” 的。
- 立即執(zhí)行版就是?觸發(fā)事件后函數(shù)不會(huì)立即執(zhí)行,而是在 n 秒后執(zhí)行,如果在 n 秒內(nèi)又觸發(fā)了事件,則會(huì)重新計(jì)算函數(shù)執(zhí)行時(shí)間。?
- “非立即執(zhí)行版” 指的是?觸發(fā)事件后函數(shù)會(huì)立即執(zhí)行,然后 n 秒內(nèi)不觸發(fā)事件才能繼續(xù)執(zhí)行函數(shù)的效果。
// 立即執(zhí)行版函數(shù)
function debounce(fn,t){let timer = null;let flag = true;return function(){clearTimeout(timer);if(flag){fn(...arguments);flag = false;}timer = setTimeout(() => { flag = true },t)}
}
// 非立即執(zhí)行版函數(shù)
var debounce = function(fn, t) {// 要執(zhí)行的函數(shù)(fn),延遲的時(shí)間(t)var time = null;return function(...args) {if(time){// 清除定時(shí)器clearTimeout(time);}time = setTimeout(()=>{fn(...args);},t)}
};