摘要:可以看下面的栗子這個圖中圖中每個小格大約,右邊有原生事件與節(jié)流去抖插件的與事件。即如果有連續(xù)不斷的觸發(fā),每執(zhí)行一次,用在每隔一定間隔執(zhí)行回調(diào)的場景。執(zhí)行啦打印執(zhí)行啦打印執(zhí)行啦節(jié)流按照上面的說明,節(jié)流就是連續(xù)多次內(nèi)的操作按照指定的間隔來執(zhí)行。
一般在項目中我們會對input、scroll、resize等事件進行節(jié)流控制,防止事件過多觸發(fā),減少資源消耗;在vue的官網(wǎng)的例子中就有關(guān)于lodash的debounce方法的使用,當(dāng)時也提到了throttle,但一直沒搞明白節(jié)流 throttle 與 去抖 debounce具體區(qū)別在哪里,所以花了點時間來搞清楚。
1. 區(qū)別節(jié)流 throttle 與 去抖 debounce的區(qū)別主要在觸發(fā)時機上:
debounce(func, wait, options):創(chuàng)建并返回函數(shù)的防反跳版本,將延遲函數(shù)的執(zhí)行(真正的執(zhí)行)在函數(shù)最后一次調(diào)用時刻的wait毫秒之后,對于必須在一些輸入(多是一些用戶操作)停止之后再執(zhí)行的行為有幫助。將一個連續(xù)的調(diào)用歸為一個,如果連續(xù)在wait毫秒內(nèi)調(diào)用,最后只有最后一次會執(zhí)行
throttle(func, wait, options):創(chuàng)建并返回一個像節(jié)流閥一樣的函數(shù),當(dāng)重復(fù)調(diào)用函數(shù)的時候,最多每隔指定的wait毫秒調(diào)用一次該函數(shù);不允許方法在每wait毫秒間執(zhí)行超過一次,如果連續(xù)在wait毫秒內(nèi)調(diào)用,最后執(zhí)行會均勻分布在大約每wait一次
對于lodash來說,throttle是調(diào)用debounce來實現(xiàn)的,throttle 和 debounce 最終都會都會調(diào)用 debounce 方法。當(dāng)調(diào)用 _.debouncelodash會返回一個函數(shù),這個函數(shù)在被調(diào)用時會生成一個 setTimeout(delayed, delay)。其中 delayed 又是一個內(nèi)部方法,在 delayed 被調(diào)用時進行如下檢測:當(dāng)前時間 - 上次func被調(diào)用事件 是否 小于 0 或 大于 delay ?如果是則執(zhí)行一次 func,記錄并返回執(zhí)行結(jié)果,同時更新上次被調(diào)用時間;如果不是則調(diào)用 setTimeout 進行下一次的判斷。_.throttle 方法只不過是多給 debounce 傳了一個 options = {maxWait: $maxWait, leading: true, trailing: true},這個選項的意思是至少保證在每 maxWait 時間讓 func 被調(diào)用一次。
可以看下面的栗子:
這個圖中圖中每個小格大約30ms,右邊有原生mouseover事件、lodash與jQuery節(jié)流去抖插件的debounce與throttle事件。
在圖左區(qū)域移動鼠標(biāo)時:對于debounce,mouseover事件一直沒有被調(diào)用,直到停下來才被調(diào)用一次。而throttle是每wait毫秒就調(diào)用一次。
debounce:第一次觸發(fā)后,進行倒計wait毫秒,如果倒計時過程中有其他觸發(fā),則重置倒計時;否則執(zhí)行。用它來丟棄一些重復(fù)的密集操作,直到流量減慢。
throttle:第一次觸發(fā)后先執(zhí)行fn(lodash可以通過{leading: false}來取消),然后wait ms后再次執(zhí)行,在單位wait毫秒內(nèi)的所有重復(fù)觸發(fā)都被拋棄。即如果有連續(xù)不斷的觸發(fā),每wait ms執(zhí)行fn一次,用在每隔一定間隔執(zhí)行回調(diào)的場景。
mouse move 時減少計算次數(shù):debounce
input 中輸入文字自動發(fā)送 ajax 請求進行自動補全: debounce
ajax 請求合并,不希望短時間內(nèi)大量的請求被重復(fù)發(fā)送:debounce
resize window 重新計算樣式或布局:debounce 或 throttle
scroll 時觸發(fā)操作,如隨動效果:throttle
對用戶輸入的驗證,不想停止輸入再進行驗證,而是每n秒進行驗證:throttle
3. 簡單實現(xiàn) 3.1 去抖 debounce按照上面的說明,去抖就是連續(xù)多次delay內(nèi)的操作取最后一次操作真正執(zhí)行。
let reduceEvent function debounce(cb, delay) { if (!reduceEvent) { reduceEvent = setTimeout(() => { cb() console.log("執(zhí)行啦!!") reduceEvent = null }, delay) } } setTimeout(() => debounce(() => console.log(1), 2000), 1000) // 打印: 1 執(zhí)行啦!! setTimeout(() => debounce(() => console.log(2), 2000), 2000) setTimeout(() => debounce(() => console.log(3), 2000), 2000) setTimeout(() => debounce(() => console.log(4), 2000), 4000) // 打印: 4 執(zhí)行啦!!3.2 節(jié)流 throttle
按照上面的說明,節(jié)流就是連續(xù)多次delay內(nèi)的操作按照指定的間隔來執(zhí)行。
function throttle(func, wait = 200) { let last = 1 let timer return function(...rest) { const now = +new Date() if (last && now - last < wait) { clearTimeout(timer) timer = setTimeout(() => { last = now func.apply(this, rest) }, wait) } else { last = now func.apply(this, rest) clearTimeout(timer) } } } const task = throttle(() => console.log(1), 2000) setTimeout(task, 0) setTimeout(task, 500) setTimeout(task, 1000) setTimeout(task, 2000) // 打印: 1 1
網(wǎng)上的帖子大多深淺不一,甚至有些前后矛盾,在下的文章都是學(xué)習(xí)過程中的總結(jié),如果發(fā)現(xiàn)錯誤,歡迎留言指出~
參考:
lodash
圖解 debounce 與 throttle 的區(qū)別
debounce與throttle區(qū)別
Debouncing and Throttling Explained Through Examples
Debounce and Throttle: a visual explanation
PS:歡迎大家關(guān)注我的公眾號【前端下午茶】,一起加油吧~
另外可以加入「前端下午茶交流群」微信群,長按識別下面二維碼即可加我好友,備注加群,我拉你入群~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/94122.html
摘要:自己嘗試一下年在的文章中第一次看到的實現(xiàn)方法。這三種實現(xiàn)方法內(nèi)部不同,但是接口幾乎一致。如你所見,我們使用了參數(shù),因為我們只對用戶停止改變?yōu)g覽器大小時最后一次事件感興趣。 前幾天看到一篇文章,我的公眾號里也分享了《一次發(fā)現(xiàn)underscore源碼bug的經(jīng)歷以及對學(xué)術(shù)界拿來主義的思考》具體文章詳見,微信公眾號:showImg(https://segmentfault.com/img/b...
摘要:那么還有最后一個問題,那我之前設(shè)置的定時器怎么辦呢定時器執(zhí)行的是這個函數(shù),而這個函數(shù)又會通過進行一次判斷。 我們在處理事件的時候,有些事件由于觸發(fā)太頻繁,而每次事件都處理的話,會消耗太多資源,導(dǎo)致瀏覽器崩潰。最常見的是我們在移動端實現(xiàn)無限加載的時候,移動端本來滾動就不是很靈敏,如果每次滾動都處理的話,界面就直接卡死了。 因此,我們通常會選擇,不立即處理事件,而是在觸發(fā)一定次數(shù)或一定時間...
摘要:舉例舉例通過拖拽瀏覽器窗口,可以觸發(fā)很多次事件。不支持,所以不能在服務(wù)端用于文件系統(tǒng)事件。總結(jié)將一系列迅速觸發(fā)的事件例如敲擊鍵盤合并成一個單獨的事件。確保一個持續(xù)的操作流以每毫秒執(zhí)行一次的速度執(zhí)行。 Debounce 和 Throttle 是兩個很相似但是又不同的技術(shù),都可以控制一個函數(shù)在一段時間內(nèi)執(zhí)行的次數(shù)。 當(dāng)我們在操作 DOM 事件的時候,為函數(shù)添加 debounce 或者 th...
摘要:多次連續(xù)事件觸發(fā)動作最后一次觸發(fā)之后的指定時間間隔執(zhí)行回調(diào)函數(shù)預(yù)先設(shè)定一個執(zhí)行周期,當(dāng)調(diào)用動作的時刻大于等于執(zhí)行周期則執(zhí)行該動作,然后進入下一個新的時間周期。 定義 為了避免某個事件在較短的時間段內(nèi)(稱為 T)內(nèi)連續(xù)觸發(fā)從而引起的其對應(yīng)的事件處理函數(shù)不必要的連續(xù)執(zhí)行的一種事件處理機制(高頻觸發(fā)事件解決方案)debounce:當(dāng)調(diào)用動作觸發(fā)一段時間后,才會執(zhí)行該動作,若在這段時間間隔內(nèi)又...
摘要:主要實現(xiàn)在于通過異步操作的事件間隔,對于前后兩次調(diào)用方法打時間進行比較,用清空定時器的操作實現(xiàn)多余調(diào)用操作的舍棄。 廢話不多說,直奔主題。 什么是throttle和debounce? 這兩個方法的主要目的多是用于性能優(yōu)化。最常見的應(yīng)用嘗盡就是在通過監(jiān)聽resize、scroll、mouseover等事件時候的性能消耗。拿scroll來說,沒有處理時滑動一次滾動條scroll事件會觸發(fā)多...
閱讀 521·2023-04-26 00:33
閱讀 3546·2021-11-24 09:39
閱讀 2941·2021-09-22 15:34
閱讀 2323·2019-08-23 18:07
閱讀 2918·2019-08-23 18:04
閱讀 3707·2019-08-23 16:06
閱讀 2900·2019-08-23 15:27
閱讀 1619·2019-08-23 14:32