您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關JavaScript中函數節流的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
JavaScript 函數節流詳解
瀏覽器一個網頁的UI線程只有一個,他同時會處理界面的渲染和頁面JavaScript代碼的執行(簡單擴展一下,瀏覽器或者JavaScript運行大環境并不是單線程,諸如ajax異步回調、hybrid框架內與native通信、事件隊列、CSS運行線程等等都屬于多線程環境,不過ES6引入了Promise類來減少了部分異步情況)。因此當JavaScript代碼運行計算量很大的方法時,就有可能阻塞UI線程,小則導致用戶響應卡頓,嚴重的情況下瀏覽器會提示頁面無響應是否強制關閉。例如網頁的頁面滾動事件、移動設備的滑動、縮放事件等。即使沒有出現嚴重的性能問題,我們也應該站在性能優化的角度將短時間內會多次觸發的大規模處理時間進行分流計算。
如何有效避免UI線程運行過長的代碼,是所有用戶交互應用需要考慮的問題,同樣的問題在客戶端Android可以使用UI主線程開子線程來分散計算。與此對應的,js也可以通過引入webWorker來分散計算,但是在js中有一個更簡單并且效果不錯的方法:函數節流。使用函數節流的核心技巧就是使用定時器分段計算。具體的實現方式大致有兩種思路。
·方法一
1.這種實現方式的思路很好理解:設置一個一間隔時間,比如50毫秒,以此時間為基準設置定時器,當第一次觸發事件到第二次觸發事件間隔小于50毫秒時,清除這個定時器,并設置一個新的定時器,以此類推,直到有一次事件觸發后50毫秒內沒有重復觸發。代碼如下:
function debounce(method){ clearTimeout(method.timer); method.timer=setTimeout(function(){ method(); },50); }
這種設計方式有一個問題:本來應該多次觸發的事件,可能最終只會發生一次。具體來說,一個循序漸進的滾動事件,如果用戶滾動太快速,或者程序設置的函數節流間隔時間太長,那么最終滾動事件會呈現為一個很突然的跳躍事件,中間過程都被節流截掉了。這個例子舉的有點夸張了,不過使用這種方式進行節流最終是會明顯感受到程序比不節流的時候“更突兀”,這對于用戶體驗是很差的。有一種彌補這種缺陷的設計思路。
·方法二
2.第二種實現方式的思路與第一種稍有差別:設置一個間隔時間,比如50毫秒,以此時間為基準穩定分隔事件觸發情況,也就是說100毫秒內連續觸發多次事件,也只會按照50毫秒一次穩定分隔執行。代碼如下:
var oldTime=new Date().getTime(); var delay=50; function throttle1(method){ var curTime=new Date().getTime(); if(curTime-oldTime>=delay){ oldTime=curTime; method(); } }
相比于第一種方法,第二種方法也許會比第一種方法執行更多次(有時候意味著更多次請求后臺,即更多的流量),但是卻很好的解決了第一種方法清除中間過程的缺陷。因此在具體場景應根據情況擇優決定使用哪種方法。
對于方法二,我們再提供另一種同樣功能的寫法:
var timer=undefined,delay=50; function throttle2(method){ if(timer){ return ; } method(); timer=setTimeout(function(){ timer=undefined; },delay); }
最后說點個外話,說明一下函數節流的名稱問題,大家往往會看到throttle和debounce兩個方法名,throttle可以譯為“節制,卡住”,debounce可以譯為“防反跳”。在《JavaScript高級程序設計》中作者介紹了方法一,并且作者使用了“throttle”這個函數名。而在《第三方JavaScript編程》書中同時出現了方法一和方法二,作者將方法一命名為“debounce”,將方法二命名為“throttle”。國內在同時介紹兩個方法的時候有些文章錯誤的將方法一命名為“throttle”,而將方法二命名為“debounce”,從英語的角度來說是很不負責任的。因此在這里撥亂反正:方法一適合理解為“防反跳”,應命名為“debounce”;方法二適合理解為“函數節制”,應命名為“throttle”。
感謝各位的閱讀!關于“JavaScript中函數節流的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。