如何理解JS函數(shù)防抖和函數(shù)節(jié)流
概述
函數(shù)防抖和函數(shù)節(jié)流都是定義一個函數(shù),該函數(shù)接收一個函數(shù)作為參數(shù),并返回一個添加了防抖或節(jié)流功能后的函數(shù)。
因此可以將函數(shù)防抖和函數(shù)節(jié)流看作是一個函數(shù)工廠,負責對傳進來的函數(shù)進行相應的加工改造,然后產(chǎn)出一個新的帶有某種功能的函數(shù)。
函數(shù)防抖是某一時間內(nèi)只執(zhí)行一次,而函數(shù)節(jié)流是間隔時間執(zhí)行
假如有這樣一個場景:在某一頁面,有一個按鈕是 "加載更多",這個按鈕的作用就是使用 ajax 從后端服務器請求更多的數(shù)據(jù)展示在頁面,我們都知道,ajax 請求的響應是一個異步的,會存在一定的響應時間,如果用戶在點擊了該按鈕后,立馬又點擊了一下該按鈕,按照常規(guī)回調(diào)函數(shù)的操作,回調(diào)函數(shù)會立馬又執(zhí)行一次,那么就是用戶短時間內(nèi)點擊了兩次 "加載更多" 按鈕后就會執(zhí)行回調(diào)函數(shù)向后端發(fā)起了兩次一模一樣的 ajax 請求,服務器會一一接收請求并處理返回數(shù)據(jù),短時間內(nèi)兩次請求還好,如果用戶連續(xù)點擊了 n 次 "加載更多" 按鈕呢?那就會短時間內(nèi)向服務器發(fā)送了 n 次一模一樣的請求,每次后端處理 ajax 請求后返回數(shù)據(jù)后頁面就會重新再渲染一次,盡管內(nèi)容沒有改變,這樣就會帶來性能上的問題,不僅為服務器帶去了壓力,也為瀏覽器帶來了不必要的渲染,這就是函數(shù)頻繁執(zhí)行帶來的副作用。
那么如何設(shè)置這個按鈕的點擊事件回調(diào)函數(shù)才能減少該函數(shù)頻繁執(zhí)行帶來的副作用呢?
1. 函數(shù)防抖(debounce)
函數(shù)防抖的設(shè)計思路就是在函數(shù)執(zhí)行前加一個等待時間,在這個等待時間內(nèi)如果該函數(shù)又需要執(zhí)行一次,就重新計算等待時間,再次等待,依次類推,直到等待時間到了,還沒有等到函數(shù)又需要執(zhí)行的情況,才會執(zhí)行這個函數(shù)。
就拿上述的場景來說,假設(shè)向后臺發(fā)送 ajax 請求的響應時間大概是在 2s 左右,那就設(shè)置這個等待時間為 2s,當用戶第一次點擊"加載更多"按鈕后,該回調(diào)函數(shù)并沒有立即執(zhí)行,也就是還沒有開始發(fā)送 ajax,此時該函數(shù)在等待,如果在 2s 內(nèi)用戶又點擊了"加載更多",那就重新計算等待時間,再等待 2s ,此時 2s 過去了,用戶沒再第三次點擊"加載更多"按鈕了,那么該函數(shù)就開始執(zhí)行了,向后端發(fā)送 ajax 請求了。
函數(shù)防抖實現(xiàn)方式如下:
function debounce(fn, delay){ let timeId = null return function(){ let context = this if(timeId){window.clearTimeout(timeId)} timeId = setTimeout(()=>{ fn.apply(context, arguments) timeId = null },delay) } }
2. 函數(shù)節(jié)流(throttle)
函數(shù)節(jié)流的設(shè)計思路是在函數(shù)執(zhí)行后加一個冷卻時間,函數(shù)在第一次執(zhí)行時是立馬執(zhí)行,但在其執(zhí)行完后設(shè)置一個冷卻時間,在冷卻時間內(nèi),該函數(shù)不能再次執(zhí)行,直到冷卻時間結(jié)束允許該函數(shù)執(zhí)行了,才可以再次執(zhí)行。
就拿上述的場景來說,冷卻時間假設(shè)也設(shè)置為 2s,在用戶第一次點擊"加載更多" 后按鈕的回調(diào)函數(shù)就會執(zhí)行,也就是會向后臺發(fā)送 ajax 請求,此時用戶又立馬再次點擊了"加載更多"按鈕,由于此刻 2s 的冷卻時間還沒有到,那么就會給第二次的函數(shù)執(zhí)行加上一個延遲執(zhí)行。
function throttle(fn, delay){ let canUse = true return function(){ if(canUse){ fn.apply(this, arguments) canUse = false setTimeout(()=>canUse=true, delay) } } }
以上就是如何理解JS函數(shù)防抖和函數(shù)節(jié)流的詳細內(nèi)容,更多關(guān)于JS函數(shù)防抖和函數(shù)節(jié)流的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺談Javascript中Object與Function對象
JavaScript的面向?qū)ο笫腔谠蔚?,所有對象都有一條屬于自己的原型鏈。Object與Function可能很多看Object instanceof Function , Function instanceof Object都為true而迷惑,所以首先看下對象的實例2015-09-09JavaScript+Canvas實現(xiàn)簡單的柱狀圖
這篇文章主要為大家詳細介紹了JavaScript如何利用Canvas實現(xiàn)繪制簡單的柱狀圖,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2023-10-10JS實現(xiàn)很實用的對聯(lián)廣告代碼(可自適應高度)
這篇文章主要介紹了JS實現(xiàn)很實用的對聯(lián)廣告代碼,可實現(xiàn)固定相對位置懸浮展示及跟隨屏幕上下滑動等功能,具有一定參考借鑒價值,需要的朋友可以參考下2015-09-09