防抖(debounce)
描述:如果短時(shí)間內(nèi)大量觸發(fā)同一事件堕虹,希望在事件連續(xù)觸發(fā)的過程中并不執(zhí)行其回調(diào)函數(shù),而是等到最后一次觸發(fā)后实撒,等待一小會再執(zhí)行回調(diào)
任務(wù):
- 第一次觸發(fā)時(shí)靴患,嘗試在一小會后執(zhí)行 (舉個(gè)??:老王去做賊,先到你家門口觀察一小會豁状,伺機(jī)行動)
- 后續(xù)連續(xù)的觸發(fā)需要抑制回調(diào)的執(zhí)行 (老王:有人路過捉偏,取消行動,等5分鐘看看情況....終于泻红,沒人路過了夭禽,開干!)
function debounce(fn, delay) {
let timer = null
return function() {
if(timer) {
clearTimeout(timer) // 連續(xù)觸發(fā)時(shí)谊路,取消第一次觸發(fā)時(shí)建立的setTimeout
}
timer = setTimeout(() => {
fn()
}, delay)
}
}
上面的代碼有個(gè)問題:fn不支持傳遞參數(shù)讹躯,我們來改寫一下
function debounce(fn, delay) {
let _self = fn
let timer = null
return function() {
let args = arguments // 類似select@change,回調(diào)函數(shù)是有參數(shù)的
let _me = this
if(timer) {
clearTimeout(timer) // 連續(xù)觸發(fā)時(shí),取消第一次觸發(fā)時(shí)建立的setTimeout
}
timer = setTimeout(() => {
_self.apply(_me, args)
}, delay)
}
}
節(jié)流(throttle)
描述:同樣是短時(shí)間大量觸發(fā)同一事件的場景下潮梯,我們希望回調(diào)函數(shù)有節(jié)制地
執(zhí)行骗灶,比如200ms執(zhí)行一次
場景:
- 在具有search功能的input中執(zhí)行doSearch查詢,用戶的輸入是連續(xù)的秉馏,如果不做限制耙旦,每輸入一個(gè)字符則執(zhí)行一次查詢
- 比如在畫板中監(jiān)聽鼠標(biāo)移動(mousemove),并在位置信息文本中更新對應(yīng)的位置,mousemove事件的執(zhí)行頻率非陈芫浚快(scroll免都,resize也是類似的),則更新dom的頻率是極高的糊肤,然而用戶其實(shí)并不需要如此高的通知頻率琴昆,一秒鐘更新2,3次即可 (畫板的例子有個(gè)特殊需求馆揉,最后一次也必須執(zhí)行业舍,可以思考下)
舉個(gè)不成熟的??:你(亞索)和小明(石頭人)玩LOL
- 快R對面中單
- 好嘞,我剛學(xué)大招(第一次)升酣,Boom....suo li a ka tong舷暮,漂亮
- R它
- Boom....suo li a ka tong,你開始有點(diǎn)上頭 (假設(shè)第一次放大招沒有冷卻)
- R它...R它...R它
- 老大噩茄,我的技能在冷卻啊下面,等好了再來
- R它...R它...R它
- 你別催了,技能好了就來
任務(wù):
- 首次執(zhí)行時(shí)绩聘,跳過限制沥割,直接執(zhí)行
- 首次執(zhí)行過后及后續(xù)每次執(zhí)行后的一段時(shí)間(delay)內(nèi),不執(zhí)行
function throttle(fn, interval) {
let isFirstTime = true
let timer = null
return function() {
let args = arguments
let _me = this
if(isFirstTime) {
_self.apply(_me, args)
isFirstTime = false
return false
}
if(timer) {
return false
}
timer = setTimeout(() => {
clearTimeout(timer) // 注意為什么寫在_self.apply()前面凿菩,函數(shù)的執(zhí)行需要時(shí)間机杜,時(shí)效性考慮
timer = null
_self.apply(_me, args)
}, interval || 200)
}
}