摘要:函數(shù)分析標簽空格分隔本文是源碼剖析系列第六篇文章,上節(jié)我們介紹了節(jié)流函數(shù)的實現(xiàn),這節(jié)將會介紹一下節(jié)流函數(shù)的兄弟防抖動函數(shù)。函數(shù)是在高頻率觸發(fā)的情況下,為了防止函數(shù)的頻繁調(diào)用,將其限制在一段時間內(nèi)只會調(diào)用一次。
underscore debounce函數(shù)分析
標簽(空格分隔): underscore
本文是underscore源碼剖析系列第六篇文章,上節(jié)我們介紹了throttle節(jié)流函數(shù)的實現(xiàn),這節(jié)將會介紹一下節(jié)流函數(shù)的兄弟 —— debounce防抖動函數(shù)。
throttle函數(shù)是在高頻率觸發(fā)的情況下,為了防止函數(shù)的頻繁調(diào)用,將其限制在一段時間內(nèi)只會調(diào)用一次。而debounce函數(shù)則是在頻繁觸發(fā)的情況下,只在觸發(fā)的最后一次調(diào)用一次,想像一下如果我們用手按住一個彈簧,那么只有等到我們把手松開,彈簧才會彈起來,下面我用一個電梯的例子來介紹debounce函數(shù)。
假如我下班的時候去坐電梯,等了一段時間后,電梯正準備關(guān)上門下降,這個時候一個同事走了過來,電梯門被打開,這樣電梯就會繼續(xù)等一段時間,如果中間一直有人進來,那么電梯就一直不會下降,直到最后一個人進來后過了一定時間后還沒有下一個人進來,這時電梯才會下降。
應(yīng)用場景除了電梯,事實上我們還有很多應(yīng)用場景,比如我用鍵盤不斷輸入文字,我希望等最后一次輸入結(jié)束后才會調(diào)用接口來請求展示聯(lián)想詞,如果每次輸入一個字的時候就會調(diào)用接口,這樣調(diào)用未免太過于頻繁了。
沒有debounce時:
有debounce時:
知道debounce的工作原理了,我們可以先自己實現(xiàn)一個比較簡單的debounce函數(shù)。
function debounce(func, wait) { var timeout, args, context var later = function() { func.apply(context, args) timeout = context = args = null } return function() { context = this args = arguments // 每次觸發(fā)都清理掉前一次的定時器 clearTimeout(timeout) // 只有最后一次觸發(fā)后才會調(diào)用later timeout = setTimeout(later, wait) } }
麻雀雖小,五臟俱全,不過這個函數(shù)還是有很多問題,比如每次觸發(fā)都設(shè)置了太多的setTimeout,這樣會比較耗費cpu,我們來看一下underscore的實現(xiàn)方式。
underscore debounce// debounce函數(shù)傳入三個參數(shù),分別是要執(zhí)行的函數(shù)func,延遲時間wait,是否立即執(zhí)行immediate // 如果immediate為true,那么就會在wait時間段一開始就執(zhí)行一次func,之后不管觸發(fā)多少次都不會再執(zhí)行func // 在類似不小心點了提交按鈕兩下而提交了兩次的情況下很有用 _.debounce = function (func, wait, immediate) { var timeout, args, context, timestamp, result; var later = function () { // 這個是最關(guān)鍵的一步,因為每次觸發(fā)的時候都要記錄當前timestamp // 但是later是第一次觸發(fā)后wait時間后執(zhí)行的,_now()減去第一次觸發(fā)時的時間當然是等于wait的 // 但是如果后續(xù)繼續(xù)觸發(fā),那么_.now() - timestamp肯定會小于wait // last是執(zhí)行l(wèi)ater的時間和上一次觸發(fā)的時間差 var last = _.now() - timestamp; // 如果在later執(zhí)行前還有其他觸發(fā),那么就會重新設(shè)置定時器 // last >= 0應(yīng)該是防止客戶端系統(tǒng)時間被調(diào)整 if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); // 如果last大于等于wait,也就是說設(shè)置timeout定時器后沒有再觸發(fā)過 } else { timeout = null; // 這個時候如果immediate不為true,就會立即執(zhí)行func函數(shù),這也是為什么immediate為true的時候只會執(zhí)行第一次觸發(fā) if (!immediate) { result = func.apply(context, args); // 解除引用 if (!timeout) context = args = null; } } }; return function () { context = this; args = arguments; // 每次觸發(fā)都用timestamp記錄時間戳 timestamp = _.now(); // 第一次進來的時候,如果immediate為true,那么會立即執(zhí)行func var callNow = immediate && !timeout; // 第一次進來的時候會設(shè)置一個定時器 if (!timeout) timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); context = args = null; } return result; }; };
為了防止出現(xiàn)我們上面那種不停地設(shè)置定時器的情況,underscore只在later函數(shù)中在上一次定時器執(zhí)行結(jié)束后才重新設(shè)置定時器。
如果傳入的immediate為true,那么只會在第一次進來的時候立即執(zhí)行。很明顯在上面代碼中func執(zhí)行只有兩處,一個是callNow判斷里面,一個是!immediate判斷里面,所以這樣保證了后續(xù)觸發(fā)不會再執(zhí)行func。
參考鏈接:
1、淺談throttle以及debounce的原理和實現(xiàn)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/93668.html
摘要:函數(shù)分析標簽空格分隔本文是源碼剖析系列第六篇文章,上節(jié)我們介紹了節(jié)流函數(shù)的實現(xiàn),這節(jié)將會介紹一下節(jié)流函數(shù)的兄弟防抖動函數(shù)。函數(shù)是在高頻率觸發(fā)的情況下,為了防止函數(shù)的頻繁調(diào)用,將其限制在一段時間內(nèi)只會調(diào)用一次。 underscore debounce函數(shù)分析 標簽(空格分隔): underscore 本文是underscore源碼剖析系列第六篇文章,上節(jié)我們介紹了throttle節(jié)流函...
摘要:直接來分析返回的匿名函數(shù)部分。我第一次調(diào)用事件函數(shù)是在,按照設(shè)定,之后才能調(diào)用第二次方法,在這秒內(nèi),任何調(diào)用都是不執(zhí)行的。這個難點解決了,其他就都好說。恩,那這個的解讀就結(jié)束了,有什么地方我沒寫清楚的話,請給我留言。 剛寫完一篇debounce(防抖)函數(shù)的實現(xiàn),我又看了下underscore.js的實現(xiàn)方法。算是趁熱打鐵,分析一下underscore里實現(xiàn)的套路。 先貼上源碼: _....
摘要:事情是如何發(fā)生的最近干了件事情,發(fā)現(xiàn)了源碼的一個。樓主找到的關(guān)于和區(qū)別的資料如下關(guān)于拿來主義為什么這么多文章里會出現(xiàn)澤卡斯的錯誤代碼樓主想到了一個詞,叫做拿來主義。的文章,就深刻抨擊了拿來主義這一現(xiàn)象。 事情是如何發(fā)生的 最近干了件事情,發(fā)現(xiàn)了 underscore 源碼的一個 bug。這件事本身并沒有什么可說的,但是過程值得我們深思,記錄如下,各位看官仁者見仁智者見智。 平時有瀏覽別...
摘要:專題系列預(yù)計寫二十篇左右,主要研究日常開發(fā)中一些功能點的實現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究和的實現(xiàn)方式。如果有錯誤或者不嚴謹?shù)牡胤剑垊?wù)必給予指正,十分感謝。 JavaScript 專題系列第一篇,講解防抖,帶你從零實現(xiàn)一個 underscore 的 debounce 函數(shù) 前言 在前端開發(fā)中會遇到一些頻繁的事件觸發(fā),比如: window 的 r...
閱讀 2131·2019-08-29 16:53
閱讀 2706·2019-08-29 16:07
閱讀 2048·2019-08-29 13:13
閱讀 3272·2019-08-26 13:57
閱讀 1338·2019-08-26 13:31
閱讀 2441·2019-08-26 13:22
閱讀 1228·2019-08-26 11:43
閱讀 2091·2019-08-23 17:14