JS防抖和節(jié)流

使用window.addEventListener()進(jìn)行窗口的resize、scroll、輸入框?qū)崟r(shí)監(jiān)控等操作時(shí),如果時(shí)間處理函數(shù)調(diào)用的頻率無限制,會(huì)加重瀏覽器的負(fù)擔(dān),容易引起瀏覽器卡死,用戶體驗(yàn)非常的糟糕。

此時(shí)我們可以采用debounce(防抖)和throttle(節(jié)流)的方式減少調(diào)用頻率,同時(shí)又不影響實(shí)際效果。

函數(shù)防抖

函數(shù)防抖(debounce):當(dāng)持續(xù)觸發(fā)scroll事件,不會(huì)執(zhí)行handle函數(shù),當(dāng)停止scroll事件的一段時(shí)間(1000毫秒)之后事件處理函數(shù)才會(huì)執(zhí)行一次。 如果設(shè)定的時(shí)間到來之前,又一次觸發(fā)了事件,就重新開始延時(shí)。

防抖debounce代碼:

// 防抖
debounce(fn,delay){
    let timer = null //借助閉包
    return function() {
        if(timer){
            clearTimeout(timer) 
        }
        timer = setTimeout(fn,delay);
    }
}
// 處理函數(shù)
function handle() {    
    console.log(Math.random()); 
}
// 滾動(dòng)事件
window.addEventListener('scroll', debounce(handle, 1000));

當(dāng)持續(xù)觸發(fā)scroll事件時(shí),事件處理函數(shù)handle只在停止?jié)L動(dòng)1000毫秒之后才會(huì)調(diào)用一次,也就是說在持續(xù)觸發(fā)scroll事件的過程中,事件處理函數(shù)handle不會(huì)一直執(zhí)行。

函數(shù)節(jié)流

函數(shù)節(jié)流(throttle):當(dāng)持續(xù)觸發(fā)事件時(shí),保證一定時(shí)間段內(nèi)只調(diào)用一次事件處理函數(shù)。按照一定規(guī)律在某個(gè)時(shí)間間隔內(nèi)執(zhí)行。如下圖,持續(xù)觸發(fā)scroll事件時(shí),并不立即執(zhí)行handle函數(shù),每隔1000毫秒才會(huì)執(zhí)行一次handle函數(shù)。

throttle(fn,delay){
    let valid = true
    return function() {
      if(!valid){
          //休息時(shí)間 暫不接客
          return false 
      }
      // 工作時(shí)間,執(zhí)行函數(shù)并且在間隔期內(nèi)把狀態(tài)位設(shè)為無效
        valid = false
        setTimeout(() => {
            fn()
            valid = true;
        }, delay)
    }
},
// 處理函數(shù)
function handle() {    
    console.log(Math.random()); 
}
// 滾動(dòng)事件
window.addEventListener('scroll', debounce(handle, 1000));

如果一直拖著滾動(dòng)條進(jìn)行滾動(dòng),那么會(huì)以1s的時(shí)間間隔,持續(xù)執(zhí)行handle事件。

其他應(yīng)用場景舉例

1) 在頁面的無限加載場景下,我們需要用戶在滾動(dòng)頁面時(shí),每隔一段時(shí)間發(fā)一次 Ajax 請(qǐng)求,而不是在用戶停下滾動(dòng)頁面操作時(shí)才去請(qǐng)求數(shù)據(jù)。這樣的場景,就適合用節(jié)流技術(shù)來實(shí)現(xiàn)。

2) 搜索框input事件,例如要支持輸入實(shí)時(shí)搜索可以使用節(jié)流方案(間隔一段時(shí)間就必須查詢相關(guān)內(nèi)容),或者實(shí)現(xiàn)輸入間隔大于某個(gè)值(如500ms),就當(dāng)做用戶輸入完成,然后開始搜索可以使用防抖,具體使用哪種方案要看業(yè)務(wù)需求。

3)頁面resize事件,常見于需要做頁面適配的時(shí)候。需要根據(jù)最終呈現(xiàn)的頁面情況進(jìn)行dom渲染(這種情形一般是使用防抖,因?yàn)橹恍枰袛嘧詈笠淮蔚淖兓闆r)

4) 避免按鈕短時(shí)間內(nèi)重復(fù)點(diǎn)擊頻繁的觸發(fā)事件,可采用防抖,只執(zhí)行最后一次操作。

總結(jié)

函數(shù)防抖:將幾次操作合并為一此操作進(jìn)行。原理是維護(hù)一個(gè)計(jì)時(shí)器,規(guī)定在delay時(shí)間后觸發(fā)函數(shù),但是在delay時(shí)間內(nèi)再次觸發(fā)的話,就會(huì)取消之前的計(jì)時(shí)器而重新設(shè)置。這樣一來,只有最后一次操作能被觸發(fā)。

函數(shù)節(jié)流:使得一定時(shí)間內(nèi)只觸發(fā)一次函數(shù)。原理是通過判斷是否到達(dá)一定時(shí)間來觸發(fā)函數(shù)。

區(qū)別: 函數(shù)節(jié)流不管事件觸發(fā)有多頻繁,都會(huì)保證在規(guī)定時(shí)間內(nèi)一定會(huì)執(zhí)行一次真正的事件處理函數(shù),而函數(shù)防抖只是在最后一次事件后才觸發(fā)一次函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、什么是防抖和節(jié)流 Ps: 比如搜索框,用戶在輸入的時(shí)候使用change事件去調(diào)用搜索,如果用戶每一次輸入都去搜...
    拾柒_aab0閱讀 313評(píng)論 0 1
  • 防抖(debounce) 1. 什么是防抖 在時(shí)間被觸發(fā)n秒后再執(zhí)行回調(diào)函數(shù),若在這n秒中又被觸發(fā),則重新計(jì)時(shí)n秒...
    書蟲和泰迪熊閱讀 377評(píng)論 0 0
  • 今天在某勾上收到一家公司的面試請(qǐng)求,但要回答幾個(gè)問題,第一個(gè)就是問防抖和節(jié)流,WTF?這就觸及到我知識(shí)的盲區(qū)了,沒...
    大怪獸迪迦閱讀 352評(píng)論 0 1
  • 在處理高頻事件,類似于window的resize或者scorll,或者input輸入校驗(yàn)等操作時(shí)。如果直接執(zhí)行事件...
    弗蘭克史密斯閱讀 415評(píng)論 0 0
  • 防抖:函數(shù)一定時(shí)間內(nèi)只執(zhí)行最后一次,比如一個(gè)公交司機(jī),等到最后一個(gè)乘客上車時(shí)才關(guān)門,只需要關(guān)一次 節(jié)流:函數(shù)每一段...
    呵呵_4350閱讀 328評(píng)論 0 0

友情鏈接更多精彩內(nèi)容