JS中的函數(shù)節(jié)流(throttle)

JS中的函數(shù)節(jié)流(throttle)

一、什么是函數(shù)節(jié)流(throttle)

概念:限制一個(gè)函數(shù)在一定時(shí)間內(nèi)只能執(zhí)行一次。

舉個(gè)栗子:坐火車或地鐵,過(guò)安檢的時(shí)候,在一定時(shí)間(例如10秒)內(nèi),只允許一個(gè)乘客通過(guò)安檢入口,以配合安檢人員完成安檢工作。上例中,每10秒內(nèi),僅允許一位乘客通過(guò),分析可知,“函數(shù)節(jié)流” 的要點(diǎn)在于,在一定時(shí)間之內(nèi),限制一個(gè)動(dòng)作只能執(zhí)行一次。

二、為什么需要函數(shù)節(jié)流

前端開(kāi)發(fā)過(guò)程中,有一些事件或者函數(shù),會(huì)被頻繁地觸發(fā)(短時(shí)間按內(nèi)多次觸發(fā)),最常見(jiàn)的例如,onresize,scroll,mousemove ,mousehover 等,這些事件的觸發(fā)頻率很高,不做限制的話,有可能一秒之內(nèi)執(zhí)行幾十次、幾百次,如果在這些函數(shù)內(nèi)部執(zhí)行了其他函數(shù),尤其是執(zhí)行了操作 DOM 的函數(shù)(瀏覽器操作 DOM 是很耗費(fèi)性能的),那不僅會(huì)造成計(jì)算機(jī)資源的浪費(fèi),還會(huì)降低程序運(yùn)行速度,甚至造成瀏覽器卡死、崩潰。這種問(wèn)題顯然是致命的。

除此之外,重復(fù)的 ajax 調(diào)用不僅可能會(huì)造成請(qǐng)求數(shù)據(jù)的混亂,還會(huì)造成網(wǎng)絡(luò)擁塞,占用服務(wù)器帶寬,增加服務(wù)器壓力,顯然這個(gè)問(wèn)題也是需要解決的。

三、函數(shù)節(jié)流如何解決上述問(wèn)題

根據(jù)上面對(duì)問(wèn)題的分析,細(xì)細(xì)思索,問(wèn)題的解決方案就呼之欲出啦。

主要實(shí)現(xiàn)思路就是通過(guò) setTimeout 定時(shí)器,通過(guò)設(shè)置延時(shí)時(shí)間,在第一次調(diào)用時(shí),創(chuàng)建定時(shí)器,先設(shè)定一個(gè)變量 true, 寫(xiě)入需要執(zhí)行的函數(shù),第二次執(zhí)行這個(gè)函數(shù)時(shí),會(huì)判斷變量是否 true,是則返回。當(dāng)?shù)谝淮蔚亩〞r(shí)器執(zhí)行完函數(shù)最后會(huì)設(shè)定變量為 false。那么下次判斷變量時(shí)則為 false, 函數(shù)會(huì)依次執(zhí)行。目的在于在一定的時(shí)間內(nèi),保證多次函數(shù)的請(qǐng)求只執(zhí)行最后一次調(diào)用。

四、函數(shù)節(jié)流的代碼實(shí)現(xiàn)

根據(jù)以上分析,我們對(duì)“函數(shù)節(jié)流”進(jìn)行代碼實(shí)現(xiàn),如下:

(1) 方法一:時(shí)間戳方案

// 時(shí)間戳方案
function throttle(fn, wait) {
    let pre = Date.now()
    return function () {
        let _this = this
        let _arguments = arguments
        let now = Date.now()
        if (now - pre >= wait) {
            fn.apply(_this, _arguments)
            pre = Date.now()
        }
    }
}

function handle() {
    console.log(Math.random())
}

window.addEventListener('mousemove', throttle(handle, 1000))

(2) 方法二:定時(shí)器方案

// 定時(shí)器方案
function throttle(fn, wait) {
    let timer= null

    return function () {
        let _this = this
        let _arguments = arguments

        if (!timer) {
            timer = setTimeout(function () {
                fn.apply(_this, _arguments)
                timer = null
            }, wait)
        }
    }
}

function handle() {
    console.log(Math.random())
}

window.addEventListener('mousemove', throttle(handle, 1000))

以上兩種方法本人都親自測(cè)試過(guò),小伙伴們可以放心食用(注意,例子中函數(shù)觸發(fā)方式為 mousemove, 鼠標(biāo)在頁(yè)面上移動(dòng),觀察瀏覽器控制臺(tái)的變化),自己運(yùn)行代碼體驗(yàn)后,自然會(huì)更深刻的理解“函數(shù)節(jié)流”。

五、函數(shù)節(jié)流的使用場(chǎng)景

到此為止,相信各位應(yīng)該對(duì)函數(shù)節(jié)流有了一個(gè)比較詳細(xì)的了解,那函數(shù)節(jié)流一般用在什么情況之下呢?

  1. 懶加載、滾動(dòng)加載、加載更多或監(jiān)聽(tīng)滾動(dòng)條位置;
  2. 百度搜索框,搜索聯(lián)想功能;
  3. 防止高頻點(diǎn)擊提交,防止表單重復(fù)提交

目前遇到過(guò)的使用場(chǎng)景就是這些了,不過(guò)理解了原理,小伙伴可以把它用在需要用到它的任何場(chǎng)合,提高代碼質(zhì)量。

參考鏈接:https://segmentfault.com/a/1190000019577510,版權(quán)歸原作者所有。

?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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