摘要:譯通過實(shí)例講解和防抖與節(jié)流源碼中推薦的文章,為了學(xué)習(xí)英語(yǔ),翻譯了一下原文鏈接作者本文來自一位倫敦前端工程師的技術(shù)投稿。首次或立即你可能發(fā)現(xiàn)防抖事件在等待觸發(fā)事件執(zhí)行,直到事件都結(jié)束后它才執(zhí)行。
[譯]通過實(shí)例講解Debouncing和Throtting(防抖與節(jié)流)
lodash源碼中推薦的文章,為了學(xué)習(xí)(英語(yǔ)),翻譯了一下~
原文鏈接作者:DAVID CORBACHO
本文來自一位倫敦前端工程師DAVID CORBACHO的技術(shù)投稿。我們?cè)谥坝懻撨^這個(gè)話題(關(guān)于防抖與節(jié)流),但這次,DAVID CORBACHO通過生動(dòng)的演示會(huì)將它們講的十分清晰,通俗易懂。
Debounce和throttle是兩個(gè)相似(但實(shí)現(xiàn)原理不一樣)的技術(shù)手段,用于控制一個(gè)函數(shù)在一段時(shí)間內(nèi)執(zhí)行幾次。
當(dāng)我們的函數(shù)附著在dom事件上時(shí),使用Debounce和throttle去處理這個(gè)函數(shù)是十分有用的。為什么呢?因?yàn)槲覀冊(cè)谑录蛨?zhí)行函數(shù)之間加了一個(gè)控制層。需要注意的是,這里并不是去控制dom事件發(fā)生的頻率。
我們來看一個(gè)滑動(dòng)事件的例子:
例子鏈接
當(dāng)我們使用觸控板、滾輪、或者是拉動(dòng)滑動(dòng)條,事件可能每秒僅僅觸發(fā)了30次左右。但如果我們滑的比較慢,他可能觸發(fā)100次。對(duì)于這些不一致的數(shù)據(jù),你在處理的時(shí)候是否考慮到了?
2011年的時(shí)候,推特網(wǎng)上出現(xiàn)了一個(gè)問題:當(dāng)你緩慢地在推特上往下滾動(dòng)時(shí),網(wǎng)站開始變得卡頓甚至沒有反應(yīng)。John Resig針對(duì)該問題發(fā)了一條博客learning-from-twitter,他覺得在scroll事件上附著復(fù)雜的函數(shù)處理是十分糟糕的。
John給出的解決方案是在scroll事件結(jié)束后,每250毫秒做循環(huán)執(zhí)行(感興趣的可以去看上面那篇博客,此時(shí)應(yīng)該是Debounce得雛形)。這種處理耦合度低,而且避免了破壞用戶體驗(yàn)。
如今處理事件的方式復(fù)雜了不少,下面向你們介紹Debounce, Throttle,對(duì)應(yīng)的也舉一些例子。
DebounceDebounce將一個(gè)組的多次調(diào)用處理為只調(diào)用一次。
想象你正在電梯里,電梯門準(zhǔn)備關(guān)閉,這時(shí)候有個(gè)人同時(shí)進(jìn)電梯,此時(shí)電梯并沒有開始上升(下降),而是電梯門再次打開。如果不斷地有人進(jìn)來,電梯將延遲他上升(或下降)的函數(shù),從而達(dá)到資源優(yōu)化的目標(biāo)。
你可以自己試試,點(diǎn)擊或者將鼠標(biāo)放在按鈕上。
例子鏈接
可以看到debounce將多次連續(xù)的事件整理成單次的事件。
Leading edge (or "immediate") [首次或立即]你可能發(fā)現(xiàn)防抖事件在等待觸發(fā)事件執(zhí)行,直到事件都結(jié)束后它才執(zhí)行。為什么不讓事件一開始就執(zhí)行,從而達(dá)到跟我們最初的設(shè)想一樣的效果呢?但是短時(shí)間內(nèi)不能連續(xù)執(zhí)行。
你可以看看這個(gè),這是個(gè)"leading" debounce的例子。
在underscore.js中,該配置項(xiàng)叫immediate而不是leading。
你可以試試:
例子鏈接
Debounce 的實(shí)現(xiàn)我第一次看到debounce的實(shí)現(xiàn)是在John Hann(term之父)的博客中,當(dāng)時(shí)還是2009年。一年過后Jeremy Ashkenas將它加入了underscore.js。debounce最近才加入到Lodash中。
這三種實(shí)現(xiàn)方式內(nèi)部有些不同,但他們的接口十分相似。
曾經(jīng)有一段時(shí)間underscore采用了debounce中debounce/throttle 的實(shí)現(xiàn),知道2013年我在_.debounce中發(fā)現(xiàn)了一個(gè)bug,從那之后,他們分道揚(yáng)鑣。
Lodash加了很多特征在_.debounce 和 _.throttle中。原來的immediate標(biāo)識(shí)被替換成leading和trailing。你可以配置一項(xiàng),或者都配置。默認(rèn)生效的是trailing。
我在本文中不會(huì)討論新的配置項(xiàng)maxWait,雖然我不討論他,但是他很有用。事實(shí)上throttle的實(shí)現(xiàn)就是在debounce中使用了maxWait,你可以在這里看到。
Debounce 舉例 Resize 的例子當(dāng)我們?cè)谡{(diào)整瀏覽器窗口時(shí),會(huì)觸發(fā)Resize事件。
看下面的demo:
demo
可以看到,我們?cè)?b>resize事件中使用默認(rèn)配置trailing,因?yàn)槲覀冊(cè)谡{(diào)整窗口大小后只去最后一次的值。
鍵盤輸入自動(dòng)發(fā)送ajax請(qǐng)求我們做的處理是當(dāng)用戶在輸入時(shí),每50毫秒向后臺(tái)發(fā)送一次ajax請(qǐng)求。這時(shí)使用_.debounce能幫我們避免許多額外的消耗,我們僅僅在用戶停止輸入后發(fā)送一次請(qǐng)求。
這里使用leading是沒有意義的,我們需要等待用戶最后一個(gè)字符敲下。
例子鏈接
類似此場(chǎng)景的一個(gè)例子是進(jìn)行輸入驗(yàn)證,比如用戶在注冊(cè)時(shí)提示“密碼不足6位”。
如何使用debounce和throttle以及常見的坑許多人往往更傾向于寫自己的debounce/throttle函數(shù),或者ctrlC ctrlV別人博客里的代碼。我的建議是正確的去使用underscore 和 Lodash。如果你僅僅需要_.debounce 和 _.throttle方法,你可以使用lodash-cli生成指定函數(shù)的js,使用方法如下:(webpack等打包工具的出現(xiàn)我覺得不必考慮此問題)
npm i -g lodash-cli lodash include = debounce, throttle
簡(jiǎn)單使用:
// WRONG $(window).on("scroll", function() { _.debounce(doSomething, 300); }); // RIGHT $(window).on("scroll", _.debounce(doSomething, 200)); // or var debounced_version = _.debounce(doSomething, 200); $(window).on("scroll", debounced_version); // If you need it debounced_version.cancel();Throttle
Throttle的作用是確保我們的函數(shù)在每一個(gè)毫秒?yún)^(qū)間只執(zhí)行一次。
Throttle和debounce主要的不同在于,監(jiān)聽的事件一直在發(fā)生,Throttle能確保我們執(zhí)行的函數(shù)在一個(gè)毫秒?yún)^(qū)間內(nèi)至少執(zhí)行一次。這里可能一時(shí)難以理解,但看了下面的例子之后,也許你就會(huì)茅塞頓開。
Throttling Examples 無限下拉一個(gè)常見的場(chǎng)景,用戶在下拉頁(yè)面,你需要去監(jiān)測(cè)用戶離底部多遠(yuǎn),如果接近底部時(shí),發(fā)送一個(gè)ajax請(qǐng)求獲取更多內(nèi)容,然后再拼接到頁(yè)面上。
討巧的debounce在這個(gè)場(chǎng)景下一點(diǎn)辦法都沒有,它只會(huì)在用戶停止滑動(dòng)動(dòng)作后觸發(fā)。我們需要的是用戶在接近底部時(shí)發(fā)送請(qǐng)求,此時(shí)用戶可能正在下拉滑動(dòng)條。
有了throttle我們可以經(jīng)常計(jì)算用戶離底部的距離。
例子鏈接
如有幫助,感謝點(diǎn)贊!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/99423.html
摘要:封裝方法也比較簡(jiǎn)單,書中對(duì)此問題也進(jìn)行了處理使用定時(shí)器,讓函數(shù)延遲秒后執(zhí)行,在此秒內(nèi),然后函數(shù)再次被調(diào)用,則刪除上次的定時(shí)器,取消上次調(diào)用的隊(duì)列任務(wù),重新設(shè)置定時(shí)器。 在實(shí)際開發(fā)中,函數(shù)一定是最實(shí)用最頻繁的一部分,無論是以函數(shù)為核心的函數(shù)式編程,還是更多人選擇的面向?qū)ο笫降木幊蹋紩?huì)有函數(shù)的身影,所以對(duì)函數(shù)進(jìn)行深入的研究是非常有必要的。 函數(shù)節(jié)流 比較直白的說,函數(shù)節(jié)流就是強(qiáng)制規(guī)定一...
摘要:防抖防抖的作用是將多個(gè)連續(xù)的調(diào)用合并為一次調(diào)用。防抖與節(jié)流之間的重要區(qū)別是,防抖是基于上次調(diào)用來計(jì)算的而節(jié)流是基于上次調(diào)用來計(jì)算的,只要距離上次調(diào)用超過了,就可以進(jìn)行下次調(diào)用。實(shí)現(xiàn)修改自參考資料。個(gè)人認(rèn)為實(shí)現(xiàn)更好理解。 防抖(debounce) 防抖的作用是將多個(gè)連續(xù)的debounced調(diào)用合并為一次func調(diào)用。作用見參考資料1。 兩次debounced調(diào)用的間隔小于waitTim...
摘要:節(jié)流和防抖都是用來提高用戶體驗(yàn),提高網(wǎng)站性能的手段,它們的技術(shù)手段都是強(qiáng)制事件處理函數(shù)在特定的事件段內(nèi)執(zhí)行。針對(duì)上面舉例的情況,其實(shí)運(yùn)用節(jié)流和防抖都可以做到,只是它們之間又有一定的區(qū)別節(jié)流節(jié)流是在一定的時(shí)間段內(nèi),函數(shù)最多可以被調(diào)用多少次。 節(jié)流和防抖都是用來提高用戶體驗(yàn),提高網(wǎng)站性能的手段,它們的技術(shù)手段都是強(qiáng)制事件處理函數(shù)在特定的事件段內(nèi)執(zhí)行。這樣解釋可能還是不夠直觀。舉兩個(gè)例子吧:...
摘要:案例持續(xù)觸發(fā)事件時(shí),并不立即執(zhí)行函數(shù),當(dāng)毫秒內(nèi)沒有觸發(fā)事件時(shí),才會(huì)延時(shí)觸發(fā)一次函數(shù)。也以函數(shù)形式暴露普通插槽。這樣的場(chǎng)景組件用函數(shù)式組件是非常方便的。相關(guān)閱讀函數(shù)式組件自定義指令前言 有echarts使用經(jīng)驗(yàn)的同學(xué)可能遇到過這樣的場(chǎng)景,在window.onresize事件回調(diào)里觸發(fā)echartsBox.resize()方法來達(dá)到重繪的目的,resize事件是連續(xù)觸發(fā)的這意味著echarts...
摘要:文章來源詳談防抖和節(jié)流輕松理解函數(shù)節(jié)流和函數(shù)防抖函數(shù)防抖和節(jié)流好啦,今天的小菊花課堂之的防抖與節(jié)流的內(nèi)容就告一段落啦,感各位能耐心看到這里。 前言 陸游有一首《冬夜讀書示子聿》——古人學(xué)問無遺力,少壯工夫老始成。紙上得來終覺淺,絕知此事要躬行。,其中的意思想必大家都能明白,在學(xué)習(xí)或工作中,不斷的印證著這首詩(shī)的內(nèi)涵。所以,又有了此篇小菊花文章。 詳解 在前端開發(fā)中,我們經(jīng)常會(huì)碰到一些會(huì)持...
閱讀 2473·2021-11-23 09:51
閱讀 1879·2021-10-13 09:40
閱讀 1399·2021-09-30 10:01
閱讀 603·2021-09-26 09:46
閱讀 2264·2021-09-23 11:55
閱讀 1411·2021-09-10 10:51
閱讀 2277·2021-09-09 09:33
閱讀 2243·2019-08-29 17:25