JS函數(shù)節(jié)流和函數(shù)防抖問題分析
問題1:如果實現(xiàn)了dom拖拽功能,但是在綁定拖拽事件的時候發(fā)現(xiàn)每當元素稍微移動一點便觸發(fā)了大量的回調(diào)函數(shù),導致瀏覽器直接卡死,這個時候怎么辦?
**問題2:**如果給一個按鈕綁定了表單提交的post事件,但是用戶有些時候在網(wǎng)絡情況極差的情況下多次點擊按鈕造成表單重復提交,如何防止多次提交的發(fā)生?
為了應對如上場景,便出現(xiàn)了 函數(shù)防抖 和 函數(shù)節(jié)流 兩個概念,總的來說:
這兩個方法是在 時間軸上控制函數(shù)的執(zhí)行次數(shù)。
函數(shù)防抖(debounce)
概念: 在事件被觸發(fā)n秒后再執(zhí)行回調(diào),如果在這n秒內(nèi)又被觸發(fā),則重新計時。
生活中的實例: 如果有人進電梯(觸發(fā)事件),那電梯將在10秒鐘后出發(fā)(執(zhí)行事件監(jiān)聽器),這時如果又有人進電梯了(在10秒內(nèi)再次觸發(fā)該事件),我們又得等10秒再出發(fā)(重新計時)。
函數(shù)節(jié)流(throttle)
概念: 規(guī)定一個單位時間,在這個單位時間內(nèi),只能有一次觸發(fā)事件的回調(diào)函數(shù)執(zhí)行,如果在同一個單位時間內(nèi)某事件被觸發(fā)多次,只有一次能生效。
生活中的實例: 我們知道目前的一種說法是當 1 秒內(nèi)連續(xù)播放 24 張以上的圖片時,在人眼的視覺中就會形成一個連貫的動畫,所以在電影的播放(以前是,現(xiàn)在不知道)中基本是以每秒 24 張的速度播放的,為什么不 100 張或更多是因為 24 張就可以滿足人類視覺需求的時候,100 張就會顯得很浪費資源。
分析圖
假設,我們觀察的總時間為10秒鐘,規(guī)定1秒作為一次事件的最小間隔時間。
如果觸發(fā)事件的頻率是 0.5s/次 ,那么函數(shù)防抖如圖
因為始終沒法等一秒鐘就被再次觸發(fā)了,所以最終沒有一次事件是成功的。
函數(shù)節(jié)流如圖
因為控制了最多一秒一次,頻率為 0.5s/次 ,所以每一秒鐘就有一次事件作廢。最終控制成 1s/次
如果觸發(fā)事件的頻率是 2s/次 ,那么
函數(shù)防抖如圖
因為 2s/次
已經(jīng)大于了規(guī)定的最小時間,所以每計時兩秒便觸發(fā)一次。
函數(shù)節(jié)流如圖
同樣, 2s/次 大于了最小時間規(guī)定,所以每一次觸發(fā)都生效。
應用場景
對于函數(shù)防抖,有以下幾種應用場景:
- 給按鈕加函數(shù)防抖防止表單多次提交。
- 對于輸入框連續(xù)輸入進行AJAX驗證時,用函數(shù)防抖能有效減少請求次數(shù)。
- 判斷 scroll 是否滑到底部, 滾動事件 + 函數(shù)防抖
總的來說,適合多次事件 一次響應 的情況
對于函數(shù)節(jié)流,有如下幾個場景:
- 游戲中的刷新率
- DOM元素拖拽
- Canvas畫筆功能
總的來說,適合 大量事件 按時間做 平均 分配觸發(fā)。
源碼
函數(shù)防抖:
function debounce(fn, wait) {
var timer = null;
return function () {
var context = this
var args = arguments
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function () {
fn.apply(context, args)
}, wait)
}
}
var fn = function () {
console.log('boom')
}
setInterval(debounce(fn,500),1000) // 第一次在1500ms后觸發(fā),之后每1000ms觸發(fā)一次
setInterval(debounce(fn,2000),1000) // 不會觸發(fā)一次(我把函數(shù)防抖看出技能讀條,如果讀條沒完成就用技能,便會失敗而且重新讀條)
之所以返回一個函數(shù),因為防抖本身更像是一個函數(shù)修飾,所以就做了一次函數(shù)柯里化。里面也用到了閉包,閉包的變量是 timer 。
函數(shù)節(jié)流
function throttle(fn, gapTime) {
let _lastTime = null;
return function () {
let _nowTime = + new Date()
if (_nowTime - _lastTime > gapTime || !_lastTime) {
fn();
_lastTime = _nowTime
}
}
}
let fn = ()=>{
console.log('boom')
}
setInterval(throttle(fn,1000),10)
如圖是實現(xiàn)的一個簡單的函數(shù)節(jié)流,結(jié)果是 一秒打出一次boom
總結(jié)
以上所述是小編給大家介紹的JS函數(shù)節(jié)流和函數(shù)防抖問題分析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
Javascript 判斷兩個IP是否在同一網(wǎng)段實例代碼
javascript功能的強大之處是我們大家有目共睹的,幾天小編向大家介紹Javascript 判斷兩個IP是否在同一網(wǎng)段,感興趣的朋友可以參考一下2016-11-11
微信小程序?qū)崿F(xiàn)計時器開始和結(jié)束功能
這篇文章主要為大家詳細介紹了微信小程序?qū)崿F(xiàn)計時器開始和結(jié)束功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07
JavaScript探測CSS動畫是否已經(jīng)完成的方法
這篇文章主要為大家詳細介紹了JavaScript探測CSS動畫是否已經(jīng)完成的方法,感興趣的小伙伴們可以參考一下2016-08-08
移動端H5開發(fā) Turn.js實現(xiàn)很棒的翻書效果
這篇文章主要為大家詳細介紹了Turn.js實現(xiàn)很棒的翻書效果,對Turn.js翻書效果的實現(xiàn)進行總結(jié),感興趣的小伙伴們可以參考一下2016-06-06
JavaScript encodeURI 和encodeURIComponent
encodeURI和encodeURIComponet函數(shù)都是javascript中用來對URI進行編碼,將相關參數(shù)轉(zhuǎn)換成UTF-8編碼格式的數(shù)據(jù)。URI在進行定位跳轉(zhuǎn)時,參數(shù)里面的中文、日文等非ASCII編碼都會進行編碼轉(zhuǎn)換2015-12-12
jquery和css3中的選擇器nth-child使用方法和用途示例
nth-child(),是CSS3中的一個偽類選擇符,JQuery選擇器繼承了CSS的部分語法,允許通過標簽名、屬性名、內(nèi)容對DOM元素進行快速、準確的選擇。2023-03-03

