1. 程式人生 > >前端節流、防抖

前端節流、防抖

1.JS的節流、防抖及使用場景

概念和例子

在事件被觸發n秒後再執行回撥,如果在這n秒內又被觸發,則重新計時。

看一個(栗子):

//模擬一段ajax請求
function ajax(content) {
  console.log('ajax request ' + content)
}

let inputa = document.getElementById('unDebounce')

inputa.addEventListener('keyup', function (e) {
    ajax(e.target.value)
})

這裡寫圖片描述

可以看到,我們只要按下鍵盤,就會觸發這次ajax請求。不僅從資源上來說是很浪費的行為,而且實際應用中,使用者也是輸出完整的字元後,才會請求。下面我們優化一下:

function ajax(content) {
  console.log('ajax request ' + content)
}

function debounce(fun, delay) {
    return function (args) {
        let that = this
        let _args = args
        clearTimeout(fun.id)
        fun.id = setTimeout(function () {
            fun.call(that, _args)
        }, delay)
    }
}

let
inputb = document.getElementById('debounce') let debounceAjax = debounce(ajax, 500) inputb.addEventListener('keyup', function (e) { debounceAjax(e.target.value) })

看一下執行結果:
這裡寫圖片描述

可以看到,我們加入了防抖以後,當你在頻繁的輸入時,並不會傳送請求,只有當你在指定間隔內沒有輸入時,才會執行函式。如果停止輸入但是在指定間隔內又輸入,會重新觸發計時。 再看一個(栗子)。

let biu = function
() {
console.log('biu biu biu',new Date().Format('HH:mm:ss')) } let boom = function () { console.log('boom boom boom',new Date().Format('HH:mm:ss')) } setInterval(debounce(biu,500),1000) setInterval(debounce(boom,2000),1000)

這裡寫圖片描述
這個栗子就很好的解釋了,如果在時間間隔內執行函式,會重新觸發計時。biu會在第一次1.5s執行後,每隔1s執行一次,而boom一次也不會執行。因為它的時間間隔是2s,而執行時間是1s,所以每次都會重新觸發計時

就像魔獸世界裡面術士的技能條一樣 如果技能條被打斷了 就要從新讀條
看一個栗子:

function throttle(fun, delay) {
        let last, deferTimer
        return function (args) {
            let that = this
            let _args = arguments
            let now = +new Date()
            if (last && now < last + delay) {
                clearTimeout(deferTimer)
                deferTimer = setTimeout(function () {
                    last = now
                    fun.apply(that, _args)
                }, delay)
            }else {
                last = now
                fun.apply(that,_args)
            }
        }
    }

    let throttleAjax = throttle(ajax, 1000)

    let inputc = document.getElementById('throttle')
    inputc.addEventListener('keyup', function(e) {
        throttleAjax(e.target.value)
    })

看一下執行結果:
這裡寫圖片描述
可以看到,我們在不斷輸入時,ajax會按照我們設定的時間,每1s執行一次。

結合剛剛biubiubiu的栗子:

    let biubiu = function () {
        console.log('biu biu biu', new Date().Format('HH:mm:ss'))
    }

    setInterval(throttle(biubiu,1000),10)

這裡寫圖片描述

不管我們設定的執行時間間隔多小,總是1s內只執行一次。

個人理解 函式節流就是fps遊戲的射速,就算一直按著滑鼠射擊,也只會在規定射速內射出子彈。

總結

  • 函式防抖和函式節流都是防止某一時間頻繁觸發,但是這兩兄弟之間的原理卻不一樣。
  • 函式防抖是某一段時間內只執行一次,而函式節流是間隔時間執行。

使用場景

1.debounce

1.search搜尋聯想,使用者在不斷輸入值時,用防抖來節約請求資源。
2.window觸發resize的時候,不斷的調整瀏覽器視窗大小會不斷的觸發這個事件,用防抖來讓其只觸發一次。

2.throttle

1.滑鼠不斷點選觸發,mousedown(單位時間內只觸發一次)。
2.監聽滾動事件,比如是否滑到底部自動載入更多,用throttle來判斷。