轉(zhuǎn)自https://blog.coding.net/blog/the-difference-between-throttle-and-debounce-in-underscorejs
Underscore.js是一個(gè)很精干的庫,壓縮后只有5.2KB。它提供了幾十種函數(shù)式編程的方法,彌補(bǔ)了標(biāo)準(zhǔn)庫的不足,大大方便了JavaScript的編程。
本文僅探討Underscore.js的兩個(gè)函數(shù)方法 _.throttle
和 _.debounce
的原理、效果和用途。
通常的函數(shù)(或方法)調(diào)用過程分為三個(gè)部分:請(qǐng)求、執(zhí)行和響應(yīng)。(文中“請(qǐng)求”與“調(diào)用”同義,“響應(yīng)”與“返回”同義,為了更好的表述,刻意采用請(qǐng)求和響應(yīng)的說法。)
某些場景下,比如響應(yīng)鼠標(biāo)移動(dòng)或者窗口大小調(diào)整的事件,觸發(fā)頻率比較高。若稍處理函數(shù)微復(fù)雜,需要較多的運(yùn)算執(zhí)行時(shí)間,響應(yīng)速度跟不上觸發(fā)頻率,往往會(huì)出現(xiàn)延遲,導(dǎo)致假死或者卡頓感。
在運(yùn)算資源不夠的時(shí)候,最直觀的解決辦法就是升級(jí)硬件,誠然通過購買更好的硬件可以解決部分問題,但是也需要為此付出高額的成本。特別是客戶端和服務(wù)器模式,要求客戶端統(tǒng)一升級(jí)硬件基本不可能。
在資源有限的前提下,處理函數(shù)無法即時(shí)響應(yīng)高頻調(diào)用。退而求其次,只響應(yīng)部分請(qǐng)求是否可行呢?某些場景下的密集性請(qǐng)求,具備很強(qiáng)的同質(zhì)和連續(xù)性。比如說,鼠標(biāo)移動(dòng)的軌跡參數(shù)。響應(yīng)越及時(shí)效果越平滑,但是如果響應(yīng)速度跟不上時(shí),反而會(huì)出現(xiàn)卡頓感,如果適當(dāng)?shù)膩G棄一些請(qǐng)求效果更流暢。
throttle
和 debounce
是解決請(qǐng)求和響應(yīng)速度不匹配問題的兩個(gè)方案。二者的差異在于選擇不同的策略。
電梯超時(shí)
想象每天上班大廈底下的電梯。把電梯完成一次運(yùn)送,類比為一次函數(shù)的執(zhí)行和響應(yīng)。假設(shè)電梯有兩種運(yùn)行策略 throttle
和 debounce
,超時(shí)設(shè)定為15秒,不考慮容量限制。
throttle
策略的電梯。保證如果電梯第一個(gè)人進(jìn)來后,15秒后準(zhǔn)時(shí)運(yùn)送一次,不等待。如果沒有人,則待機(jī)。
debounce
策略的電梯。如果電梯里有人進(jìn)來,等待15秒。如果又人進(jìn)來,15秒等待重新計(jì)時(shí),直到15秒超時(shí),開始運(yùn)送。
function log( event ) {
console.log( $(window).scrollTop(), event.timeStamp );
};
// 控制臺(tái)記錄窗口滾動(dòng)事件,觸發(fā)頻率比你想象的要快
$(window).scroll( log );
// 控制臺(tái)記錄窗口滾動(dòng)事件,每250ms最多觸發(fā)一次
$(window).scroll( _.throttle( log, 250 ) );
function ajax_lookup( event ) {
// 對(duì)輸入的內(nèi)容$(this).val()執(zhí)行 Ajax 查詢
};
// 字符輸入的頻率比你預(yù)想的要快,Ajax 請(qǐng)求來不及回復(fù)。
$('input:text').keyup( ajax_lookup );
// 當(dāng)用戶停頓250毫秒以后才開始查找
$('input:text').keyup( _.debounce( ajax_lookup, 250 ) );