欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript 函數(shù)節(jié)流詳解及方法總結(jié)

 更新時(shí)間:2017年02月09日 09:02:26   投稿:lqh  
這篇文章主要介紹了JavaScript 函數(shù)節(jié)流詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下

JavaScript 函數(shù)節(jié)流詳解

瀏覽器一個網(wǎng)頁的UI線程只有一個,他同時(shí)會處理界面的渲染和頁面JavaScript代碼的執(zhí)行(簡單擴(kuò)展一下,瀏覽器或者JavaScript運(yùn)行大環(huán)境并不是單線程,諸如ajax異步回調(diào)、hybrid框架內(nèi)與native通信、事件隊(duì)列、CSS運(yùn)行線程等等都屬于多線程環(huán)境,不過ES6引入了Promise類來減少了部分異步情況)。因此當(dāng)JavaScript代碼運(yùn)行計(jì)算量很大的方法時(shí),就有可能阻塞UI線程,小則導(dǎo)致用戶響應(yīng)卡頓,嚴(yán)重的情況下瀏覽器會提示頁面無響應(yīng)是否強(qiáng)制關(guān)閉。例如網(wǎng)頁的頁面滾動事件、移動設(shè)備的滑動、縮放事件等。即使沒有出現(xiàn)嚴(yán)重的性能問題,我們也應(yīng)該站在性能優(yōu)化的角度將短時(shí)間內(nèi)會多次觸發(fā)的大規(guī)模處理時(shí)間進(jìn)行分流計(jì)算。

如何有效避免UI線程運(yùn)行過長的代碼,是所有用戶交互應(yīng)用需要考慮的問題,同樣的問題在客戶端Android可以使用UI主線程開子線程來分散計(jì)算。與此對應(yīng)的,js也可以通過引入webWorker來分散計(jì)算,但是在js中有一個更簡單并且效果不錯的方法:函數(shù)節(jié)流。使用函數(shù)節(jié)流的核心技巧就是使用定時(shí)器分段計(jì)算。具體的實(shí)現(xiàn)方式大致有兩種思路。

·方法一

1.這種實(shí)現(xiàn)方式的思路很好理解:設(shè)置一個一間隔時(shí)間,比如50毫秒,以此時(shí)間為基準(zhǔn)設(shè)置定時(shí)器,當(dāng)?shù)谝淮斡|發(fā)事件到第二次觸發(fā)事件間隔小于50毫秒時(shí),清除這個定時(shí)器,并設(shè)置一個新的定時(shí)器,以此類推,直到有一次事件觸發(fā)后50毫秒內(nèi)沒有重復(fù)觸發(fā)。代碼如下:

function debounce(method){ 
  clearTimeout(method.timer); 
  method.timer=setTimeout(function(){ 
   method(); 
  },50); 
} 

這種設(shè)計(jì)方式有一個問題:本來應(yīng)該多次觸發(fā)的事件,可能最終只會發(fā)生一次。具體來說,一個循序漸進(jìn)的滾動事件,如果用戶滾動太快速,或者程序設(shè)置的函數(shù)節(jié)流間隔時(shí)間太長,那么最終滾動事件會呈現(xiàn)為一個很突然的跳躍事件,中間過程都被節(jié)流截掉了。這個例子舉的有點(diǎn)夸張了,不過使用這種方式進(jìn)行節(jié)流最終是會明顯感受到程序比不節(jié)流的時(shí)候“更突兀”,這對于用戶體驗(yàn)是很差的。有一種彌補(bǔ)這種缺陷的設(shè)計(jì)思路。

·方法二

2.第二種實(shí)現(xiàn)方式的思路與第一種稍有差別:設(shè)置一個間隔時(shí)間,比如50毫秒,以此時(shí)間為基準(zhǔn)穩(wěn)定分隔事件觸發(fā)情況,也就是說100毫秒內(nèi)連續(xù)觸發(fā)多次事件,也只會按照50毫秒一次穩(wěn)定分隔執(zhí)行。代碼如下:

var oldTime=new Date().getTime(); 
var delay=50; 
function throttle1(method){ 
  var curTime=new Date().getTime(); 
  if(curTime-oldTime>=delay){ 
   oldTime=curTime; 
   method(); 
  } 
} 

相比于第一種方法,第二種方法也許會比第一種方法執(zhí)行更多次(有時(shí)候意味著更多次請求后臺,即更多的流量),但是卻很好的解決了第一種方法清除中間過程的缺陷。因此在具體場景應(yīng)根據(jù)情況擇優(yōu)決定使用哪種方法。

對于方法二,我們再提供另一種同樣功能的寫法:

var timer=undefined,delay=50; 
function throttle2(method){ 
  if(timer){ 
    return ; 
  } 
  method(); 
  timer=setTimeout(function(){ 
    timer=undefined; 
  },delay); 
} 

最后說點(diǎn)個外話,說明一下函數(shù)節(jié)流的名稱問題,大家往往會看到throttle和debounce兩個方法名,throttle可以譯為“節(jié)制,卡住”,debounce可以譯為“防反跳”。在《JavaScript高級程序設(shè)計(jì)》中作者介紹了方法一,并且作者使用了“throttle”這個函數(shù)名。而在《第三方JavaScript編程》書中同時(shí)出現(xiàn)了方法一和方法二,作者將方法一命名為“debounce”,將方法二命名為“throttle”。國內(nèi)在同時(shí)介紹兩個方法的時(shí)候有些文章錯誤的將方法一命名為“throttle”,而將方法二命名為“debounce”,從英語的角度來說是很不負(fù)責(zé)任的。因此在這里撥亂反正:方法一適合理解為“防反跳”,應(yīng)命名為“debounce”;方法二適合理解為“函數(shù)節(jié)制”,應(yīng)命名為“throttle”。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

最新評論