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