當前位置:編程學習大全網 - 編程語言 - JavaScript 函數節流和函數防抖之間的區別

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”,從英語的角度來說是很不負責任的。因此在這裏撥亂反正:方法壹適合理解為“防反跳”,應命名

  • 上一篇:c++的繼續學習
  • 下一篇:號稱“真正的智能汽車”,智己汽車有什麽料?
  • copyright 2024編程學習大全網