一文教你實(shí)現(xiàn)JavaScript防抖優(yōu)化代碼
前言
在我們前端編程中,假如我們要給后端發(fā)送請(qǐng)求,萬(wàn)一手抖多點(diǎn)了幾次,多發(fā)送了幾遍怎么辦?
解決方案:防抖!這種事就要交給我們專業(yè)的“防抖”先生來(lái)處理!
今天,我們就來(lái)教大家手搓“防抖”
為什么要防抖
就好比我們想象一個(gè)場(chǎng)景:當(dāng)我們?cè)谑褂梦覀兊捻?yè)面,我們頁(yè)面有一個(gè)提交數(shù)據(jù)的按鈕!我們每次點(diǎn)擊提交按鈕,都會(huì)向我們的后端服務(wù)器發(fā)送一個(gè)請(qǐng)求!接下來(lái)我們來(lái)構(gòu)建一下這樣一個(gè)簡(jiǎn)單的頁(yè)面!
<button id="submit">提交</button>
<script>
let sub = document.getElementById('submit')
sub.addEventListener('click',function(){
console.log('已提交');
})
</script>
這樣,我們就實(shí)現(xiàn)了一個(gè)提交按鈕!
想象一下!我們每次點(diǎn)擊按鈕都會(huì)輸出一個(gè)"已提交",代表我們向后端服務(wù)器發(fā)送了一個(gè)請(qǐng)求!

這樣我們請(qǐng)求發(fā)送成功了!但是大家發(fā)現(xiàn)沒有?如果我們多次點(diǎn)擊,就會(huì)多次輸出“已提交”,也就意味著!我們點(diǎn)了多次,就會(huì)向我們的服務(wù)器后端發(fā)送多個(gè)請(qǐng)求!!
這會(huì)造成什么后果?
- 服務(wù)器壓力增大:假如用戶體量一大!在同一段時(shí)間內(nèi)一個(gè)人同時(shí)發(fā)送多個(gè)請(qǐng)求給我們后端,每次點(diǎn)擊都會(huì)向服務(wù)器發(fā)送一個(gè)請(qǐng)求,如果點(diǎn)擊的頻率過高或者同時(shí)點(diǎn)擊的人數(shù)過多,服務(wù)器可能會(huì)承受不住壓力,導(dǎo)致響應(yīng)變慢或者服務(wù)崩潰。甚至是“冒煙??!”
- 數(shù)據(jù)重復(fù):不僅如此,如果請(qǐng)求的內(nèi)容不包含唯一標(biāo)識(shí)符(例如,時(shí)間戳、隨機(jī)數(shù)等),那么后端可能會(huì)處理重復(fù)的數(shù)據(jù)。重復(fù)處理數(shù)據(jù),做了多少無(wú)用功?
- 資源浪費(fèi):而且,過多的請(qǐng)求會(huì)消耗更多的網(wǎng)絡(luò)資源,可能會(huì)導(dǎo)致網(wǎng)絡(luò)擁堵,影響其他網(wǎng)絡(luò)活動(dòng),甚至導(dǎo)致網(wǎng)絡(luò)癱瘓!影響巨大!
- 用戶體驗(yàn)下降 由于服務(wù)器的負(fù)載增大!還會(huì)因?yàn)榭D給用戶帶來(lái)非常糟糕的體驗(yàn)!
- 安全性問題:如果每次點(diǎn)擊都會(huì)發(fā)送敏感信息(例如,密碼、個(gè)人信息等),那么可能會(huì)增加這些信息被截獲的風(fēng)險(xiǎn)。
所以,為了避免這些情況!我們就要用到今天我們要學(xué)的手段!!防止抖動(dòng)!!
如何實(shí)現(xiàn)抖動(dòng)?專業(yè)的事要用專業(yè)的方法!
當(dāng)我們處理一些頻繁觸發(fā)的事件時(shí),比如用戶輸入、滾動(dòng)等,有時(shí)候我們希望在一連串的觸發(fā)中只執(zhí)行一次相應(yīng)的操作,以減輕系統(tǒng)的負(fù)擔(dān),提高性能。這時(shí),防抖(Debouncing)就成了我們的得力助手。
防抖的概念很容易理解,就好比你在按電梯的按鈕。你按了一次,電梯并不會(huì)立刻啟動(dòng),而是等待一段時(shí)間,如果在這段時(shí)間內(nèi)有人再按了一次,那么等待的時(shí)間就會(huì)被重置。只有當(dāng)一段時(shí)間內(nèi)沒有新的按壓事件發(fā)生,電梯才會(huì)啟動(dòng)。
在JavaScript中,防抖通常通過設(shè)置一個(gè)延遲時(shí)間來(lái)實(shí)現(xiàn)。當(dāng)事件觸發(fā)時(shí),我們會(huì)等待一段時(shí)間,如果在這段時(shí)間內(nèi)沒有再次觸發(fā)事件,那么我們執(zhí)行相應(yīng)的操作。
我們來(lái)給大家上代碼!!再為大家細(xì)細(xì)解說!
<button id="btn">提交</button>
<script>
let btn = document.getElementById('btn');
function send() {
console.log('已提交');
}
//addEventListener會(huì)把this指向你綁定的對(duì)象
btn.addEventListener('click', debounce(send,1000))
function debounce(fn,delay) {
let timer;
let _this = this
return function() {
//arguments
let args = arguments
if(timer)clearTimeout(timer);//clearTimeout(timer);掐滅定時(shí)器
timer = setTimeout(()=>{
fn(this,...args)
},delay)
}
}
</script>
這就是我們防止抖動(dòng)的效果!為大家解釋一下如何實(shí)現(xiàn)呢?
- 在
Script中我們用btn獲取id='btn'的元素。 - 接下來(lái)我們聲明了一個(gè)
send函數(shù),用于發(fā)送請(qǐng)求!console.log('已提交'); - 我們?cè)谟?code>btn添加一個(gè)事件監(jiān)聽點(diǎn)擊
click事件,當(dāng)監(jiān)聽到點(diǎn)擊時(shí)候之后運(yùn)行debounce(send,1000)函數(shù),其中接收兩個(gè)參數(shù)send為之前聲明的函數(shù),1000為一個(gè)時(shí)間,傳入定時(shí)器為時(shí)間1s! - 緊接著,我們又定義一個(gè)函數(shù)
debounce(fn,delay)接收兩個(gè)參數(shù)! - 在函數(shù)體內(nèi)部,我們又定義了一個(gè)變量
timer,用_this指向調(diào)用這個(gè)函數(shù)的執(zhí)行上下文對(duì)象,但是addEventListener會(huì)把this指向你綁定的對(duì)象。 - 最后,我們返回了一個(gè)函數(shù)體,在在這個(gè)函數(shù)體當(dāng)中,我們用
args接收fn接收的參數(shù),也就是send中接收的參數(shù),我們通過一個(gè)if語(yǔ)句,判斷,如果timer存在,就用clearTimeout()掐滅定時(shí)器!再讓timer等于一個(gè)新的定時(shí)器。
這樣意味著!如果,用戶點(diǎn)擊間隔不超過一秒,它可以讓一個(gè)函數(shù)在一段時(shí)間內(nèi)只執(zhí)行一次,而忽略其他多次調(diào)用。這段代碼中,當(dāng)用戶點(diǎn)擊按鈕后,send函數(shù)會(huì)被延遲執(zhí)行,具體的延遲時(shí)間是1000毫秒(1秒)。當(dāng)用戶連續(xù)點(diǎn)擊按鈕時(shí),send函數(shù)只會(huì)在最后一次點(diǎn)擊后1秒內(nèi)執(zhí)行一次。
這樣我們就實(shí)現(xiàn)了一個(gè)防抖,我們來(lái)看看效果!

防抖的好處
- 性能優(yōu)化:在某些場(chǎng)景下,例如用戶在輸入框中輸入文本時(shí),事件處理函數(shù)可能會(huì)非常頻繁地觸發(fā)。如果這些事件處理函數(shù)執(zhí)行時(shí)間較長(zhǎng),且沒有做防抖處理,那么就可能導(dǎo)致瀏覽器界面卡頓,用戶體驗(yàn)不佳。而如果使用了防抖處理,事件處理函數(shù)只會(huì)在最后一次事件后的一定時(shí)間內(nèi)執(zhí)行一次,從而提高了程序的性能。
- 防止多次觸發(fā):在一些需要用戶輸入的情況下,如果用戶連續(xù)觸發(fā)事件(例如連續(xù)點(diǎn)擊按鈕),而事件處理函數(shù)又沒有做防抖處理,就可能會(huì)導(dǎo)致一些不希望出現(xiàn)的結(jié)果(例如連續(xù)發(fā)送請(qǐng)求、連續(xù)執(zhí)行某些操作等)。而如果使用了防抖處理,就可以有效地防止這種情況的發(fā)生。
- 減少不必要的操作:在一些需要等待用戶輸入的場(chǎng)景下,如果用戶連續(xù)觸發(fā)事件(例如連續(xù)點(diǎn)擊按鈕),而事件處理函數(shù)又沒有做防抖處理,那么就可能會(huì)導(dǎo)致一些不必要的操作被執(zhí)行(例如連續(xù)發(fā)送請(qǐng)求、連續(xù)執(zhí)行某些操作等)。而如果使用了防抖處理,就可以有效地減少這種情況的發(fā)生。
到此這篇關(guān)于一文教你實(shí)現(xiàn)JavaScript防抖優(yōu)化代碼的文章就介紹到這了,更多相關(guān)JavaScript防抖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript生成驗(yàn)證碼并實(shí)現(xiàn)驗(yàn)證功能
這篇文章主要介紹了JavaScript生成驗(yàn)證碼并實(shí)現(xiàn)驗(yàn)證功能的相關(guān)資料,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
使用postMesssage()實(shí)現(xiàn)跨域iframe頁(yè)面間的信息傳遞方法
下面小編就為大家?guī)?lái)一篇使用postMesssage()實(shí)現(xiàn)跨域iframe頁(yè)面間的信息傳遞方法。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家一個(gè)參考。一起跟隨小編過來(lái)看看吧2016-03-03
js實(shí)現(xiàn)翻頁(yè)后保持checkbox選中狀態(tài)的實(shí)現(xiàn)方法
在項(xiàng)目中有需求如下:上下分頁(yè)后,選中的checkbox狀態(tài)保持不變2012-11-11
深入理解Javascript中的valueOf與toString
javascript中所有數(shù)據(jù)類型都擁有valueOf和toString這兩個(gè)方法,null除外。它們倆解決javascript值運(yùn)算與顯示的問題,本文將詳細(xì)介紹,有需要的朋友可以參考下2017-01-01
google廣告之另類js調(diào)用實(shí)現(xiàn)代碼
這篇文章主要介紹了google廣告之另類js調(diào)用實(shí)現(xiàn)代碼,需要的朋友可以參考下2020-08-08
在多個(gè)頁(yè)面使用同一個(gè)HTML片段的代碼
有一個(gè)比較復(fù)雜的HTML片段(A),如果把這個(gè)HTML片段嵌入到其他頁(yè)面中(B,C,D....)。 問題的關(guān)鍵是在HTML片段中有大量的JavaScript邏輯需要處理,比如說分頁(yè),點(diǎn)擊事件響應(yīng)等。2011-03-03
javascript Canvas動(dòng)態(tài)粒子連線
這篇文章主要為大家詳細(xì)介紹了javascript Canvas動(dòng)態(tài)粒子連線,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-01-01

