亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

瀏覽器一個(gè)網(wǎng)頁(yè)的UI線程只有一個(gè),他同時(shí)會(huì)處理界面的渲染和頁(yè)面JavaScript代碼的執(zhí)行(簡(jiǎn)單擴(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)重的情況下瀏覽器會(huì)提示頁(yè)面無響應(yīng)是否強(qiáng)制關(guān)閉。例如網(wǎng)頁(yè)的頁(yè)面滾動(dòng)事件、移動(dòng)設(shè)備的滑動(dòng)、縮放事件等。即使沒有出現(xiàn)嚴(yán)重的性能問題,我們也應(yīng)該站在性能優(yōu)化的角度將短時(shí)間內(nèi)會(huì)多次觸發(fā)的大規(guī)模處理時(shí)間進(jìn)行分流計(jì)算。

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

·方法一

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

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

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

·方法二

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

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

對(duì)于方法二,我們?cè)偬峁┝硪环N同樣功能的寫法:

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

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

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

相關(guān)文章

最新評(píng)論