亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

JS計數器函數執行過程解讀

2024-09-06 12:40:59
字體:
來源:轉載
供稿:網友

1、昂貴計算的處理

在復雜javascript應用程序開發中,最復雜的可能是用戶界面的單線程特性。而javascript在處理用戶交互時最好的狀況是反應遲鈍,最糟糕的情況是無響應而導致瀏覽器掛起(在javascript執行時,頁面中所有的更新操作暫停)。源于這一事實,將所有復雜操作(任何多于100ms的計算)減小到可管理的程度就勢在必行。另外,如果運行了至少5秒鐘還沒有停止,一些瀏覽器(如firefox 、opera)將產生一個提示框警告用戶腳本無相應。

這顯然是不可取的,產生一個無響應的界面并不好。但是,幾乎可以肯定的是,當你需要處理大量數據時就會出現這種情況(如處理數以千計的dom元素會導致這種情況出現)。

此時,計時器就顯得尤為有用。由于計時器能有效的暫停javascript代碼的執行,它也能阻止瀏覽器將執行的代碼掛起(只要個別代碼還不足以使瀏覽器掛起)。想到這一點,我們可以將正常的、密集的、循環計算納入到非阻塞的計算之中,讓我們看看下面這個例子,這種類型的計算是必需的。

一個長時運行的任務:

<table><tbody></tbody></table>
// normal, intensive, operation
var table = document.getelementsbytagname("tbody");
for ( var i = 0; i < 2000; i++ ) {
 var tr = document.createelement("tr");
for ( var t = 0; t < 6; t++ ){
 var td = document.createelement("td");
 td.appendchild( document.createtextnode("" + t));
 tr.appendchild( td );
 }
table.appendchild( tr );
}
}

在這個例子中,我們創建了總數為26000個dom節點,并將數字填入表中,這太昂貴了,很有可能將瀏覽器掛起以阻止用戶正常的交互。我們可以將計時器引入其中,從而得到與眾不同,也許更好的結果。

用計時器將耗時較長的任務拆分開來:

<table><tbody></tbody></table>
var table = document.getelementsbytagname("tbody");
var i = 0, max = 1999;
settimeout(function(){
 for ( var step = i + 500; i < step; i++ ) {
  var tr = document.createelement("tr");
  for ( var t = 0; t < 6; t++ ){
   var td = document.createelement("td");
   td.appendchild( document.createtextnode("" + t));
   tr.appendchild( td );
  }
 }
 table.appendchild( tr );
}
if ( i < max )
 settimeout( arguments.callee, 0 );
}, 0);

在我們修改的例子中,我們將密集的計算分成四部分,每個創建6500個節點。這些計算不太可能中斷瀏覽器正常的流。最糟糕的情況也只是這些數字可能隨時調整(例如,使其在250-500之間變化,這樣我們的每一個單元將產生3500dom個節點)。但是,給人印象最深的是我們如何改變我們的代碼以適應新的異步系統。我們需要做更多的工作以確保元素的數字正確生成(該循環不會永無休止)。這些代碼與我們初始的很相似。注意,我們使用閉包維持代碼片段間的迭代狀態,毫無疑問,不使用閉包,此代碼將更為復雜。

與原來的技術相比,使用該技術有一個明顯的變化。瀏覽器的長時掛起被4個視覺化的頁面更新替代。雖然瀏覽器嘗試著盡可能快得去執行這些代碼片段,它也在計時器的每一步操作之后渲染dom變化(就好像大量的更新)。大多數情況下,用戶覺察不到此種類型的更新,但記住它們曾經發生過很重要。

有一種情況會使該技術能專門為我服務--我構建的計算大學生日程排列的應用程序。起初,該應用程序是典型的cgi(客戶與服務器交流,服務器計算出日程表之后將其返回)。但我對它作了改變,講所有的日程計算放到客戶端,這是日程計算的視圖:

這些計算的代價相當昂貴(需要遍歷數以千計的排列以找到正確的答案)。將日程計算分割成實實在在的單元使這一問題得到了解決(用已經完成的那部分更新用戶界面)。最后,用戶提交的是快速、反應靈敏、可用性較高的用戶界面。

如此有用的技術常常令人驚奇。你會發現它經常被用于長時運行的程序之中,就像測試箱(我們在這章末尾討論它)。更為重要的是,這種技術向我們顯示了解決瀏覽器環境的限制是多么的輕而易舉,同時也為用戶提供了豐富的經驗。

|||

2、中央計時器控件

在使用計時器時,出現了一個問題--在處理大量計時器時如何管理它們。在動畫處理中你嘗試去同步處理大量屬性時就尤其重要,你需要一種方法去管理它們。

你的計時器有一個核心的控制將賦予你很大的權力和靈活性,即:

  • 在某個時刻每個頁面僅一個計時器運行;
  • 你可以隨時暫停和繼續計時器;
  • 移除回調函數不過是小菜一碟。

你也必需認識到,增加同步計時器的數量有可能增加瀏覽器垃圾回收出現的可能性。一般來說,瀏覽器在搜尋并嘗試綁定任何零碎的東西(刪除未使用的變量、對象等)。因為它們通常在正常的javascript引擎管理之外(通過其它線程),這時定時器的問題就尤為嚴重。一些瀏覽器能處理這種情況而另外一些瀏覽器會導致長時的垃圾回收循環出現。你也許會注意到這種問題--當你在一個瀏覽器中看到的是漂亮、平滑的動畫,而在另一個瀏覽器中動畫是走走停停完成的。減少計時器同步應用的數量對此大有裨益(這也是現代瀏覽器引入類似中央計時器控件構件的原因)。

讓我們來看一個例子,我們有多個函數,這些函數分別對單個屬性產生動畫效果,但它們被一個單獨的計時器函數管理。

用計時器隊列控制多重動畫:

<div id="box" style="position:absolute;">hello!</div>
var timers = {
 timerid: 0,
 timers: [],
 start: function(){
  if ( this.timerid )
   return;
  (function(){
   for ( var i = 0; i < timers.timers.length; i++ )
    if ( timers.timers[i]() === false ) {
     timers.timers.splice(i, 1);
     i--;
    }
    timers.timerid = settimeout( arguments.callee, 0 );
  })();
  },
 stop: function(){
  cleartimeout( this.timerid );
  this.timerid = 0;
  },
 add: function(fn){
  this.timers.push( fn );
  this.start();
 }
};
var box = document.getelementsbyid("box"), left = 0, top = 20;
timers.add(function(){
 box.style.left = left + "px";
 if ( ++left > 50 )
  return false;
});
timers.add(function(){
 box.style.top = top + "px";
 top += 2;
 if ( top > 120 )
  return false;
});

在這我們創建了一個中央控制結構。我們可以添加新的計時器回調函數,并可停止和開始它們的執行。此外,回調函數有能力在任何時候刪除自己,只需簡單的返回“false”即可(這比通常的cleartimeout模式更容易),讓我們逐一分析代碼看看它是如何工作的。

起初,所有回調函數連同當前計時器的id(timers.id)被存儲在一個中央數組中(timers.timers)。核心內容在start()函數內部,在這里我們需要確認得是已沒有計時器在運行,如果是那樣,就開始我們的中央計時器。

計時器包含一個循環,它遍歷所有的回調函數,并按順序執行它們,它還檢查回調函數返回的值,如果是“false”,將從執行中移除。事實證明,這是計時器管理非常簡單的方式。

有一點非常重要,用這種方式組織計時器會確?;卣{函數總是按順序執行,那樣,正常的計時器總是得不到保證(瀏覽器一個接一個的選擇執行)。

定時器的這種組織方式對于大型應用程序或任何形式的真正的javascript動畫至關重要,當我們討論如何創建跨瀏覽器動畫時,有一種解決方案肯定有助于將來任何形式的應用開發。

|||

3、異步測試

另外一種中央計時器控件能派上用場的情況是在你打算做異步測試的時候。這里的問題是當我們需要對沒有立即完成的計算執行測試時(如計時器內的一些行為或xmlhttprequest)。我們需要將測試包分解,這樣就會完全異步工作。

例如,在一個正常的測試包中,我們可以很容易的運行這些測試。但是,一旦在我們的測試中引入這種需求,我們需要分解它們并單獨處理。我們可以用下面的代碼達到我們期望的效果。

簡單的異步測試包:

(function(){
var queue = [], timer;
this.test = function(fn){
 queue.push( fn );
 resume();
};
this.pause = function(){
 clearinterval( timer );
 timer = 0;
};
this.resume = function(){
 if ( !timer )
  return;
 timer = setinterval(function(){
  if ( queue.length )
   queue.shift()();
  else
   pause();
 }, 1);
};
})();
test(function(){
 pause();
 settimeout(function(){
  assert( true, "first test completed" );
  resume();
}, 100);
});
test(function(){
 pause();
 settimeout(function(){
  assert( true, "second test completed" );
  resume();
}, 200);
});

最重要的一個方面是,傳遞給test()的每一個函數至多包含一個異步測試。其異步性是通過使用pause()和resume()函數來定義的,這些函數在異步事件前后調用。實際上,上面的代碼只不過是保持異步行為的一種手段--其包含的函數以特定的順序執行(它不完全用于本測試包,但在這非常有用)。

讓我們看看使這種行為成為可能的代碼。函數的大部分功能包含在resume()函數中,它的行為與我們前面例子中的start()方法相似,但它主要用來處理隊列數據,其主要目的是取出一個函數并執行它。如果有一個在等待,它將完全停止運行。最重要的方面是,既然隊列處理代碼完全是異步的,他就能保證在我們調用pause()函數之后嘗試執行。

這一段簡短的代碼使我們的測試以完全異步的方式執行,但仍維持著test()函數執行的順序(如果結果具有毀壞性且影響其它測試,這就非常關鍵)。謝天謝地,我們可以看到,使用最有效的計時器,給一個存在的測試包增加可靠的異步測試并不需要所有的開銷。

|||

4、總結

了解javascript函數如何工作啟發了我們:這些看似簡單的特征在其執行時相當復雜。但是,考慮到它的復雜性,我們會更加深入的研究它們。很明顯,計時器最終在復雜的應用程序中特別有用(計算昂貴的代碼、動畫、異步測試包)。但由于其易用性(特別是增加了閉包),它們往往易于掌握,即使是在最復雜的情況下。

附文章中提到的assert()函數:(該函數是在jquery的基礎上創建的)

function assert(pass, msg){
  var type = pass ? "pass" : "fail";
  jquery("#results").append("<li class='" + type + "'><b>" + type + "</b> " + msg + "</li>");
}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人精品一区| 日韩激情片免费| 欧美日韩国产精品一区二区不卡中文| 欧美极品少妇xxxxx| 亚洲乱码国产乱码精品精天堂| 影音先锋日韩有码| 欧美国产日韩一区| 日韩免费看的电影电视剧大全| 日韩欧美在线视频| 亚洲乱码一区av黑人高潮| 国产99久久精品一区二区永久免费| 91精品免费久久久久久久久| 精品国产欧美成人夜夜嗨| 中文综合在线观看| 亚洲欧洲偷拍精品| 亚洲国产成人在线播放| 日韩精品在线观看视频| 9.1国产丝袜在线观看| 国产欧美精品xxxx另类| 亚洲精品综合精品自拍| 成人福利网站在线观看11| 亚洲精品国产suv| 国产精品久久久久久久久久99| 国产精品视频地址| 97精品国产97久久久久久免费| 亚洲午夜久久久影院| 在线视频欧美性高潮| 亚洲天堂av高清| 色噜噜亚洲精品中文字幕| 亚洲精品免费一区二区三区| 成人av番号网| 久久不射热爱视频精品| 亚洲欧洲国产一区| 日韩电影大全免费观看2023年上| 亚洲成人a级网| 国产日韩亚洲欧美| 欧美高清视频一区二区| 欧美一级bbbbb性bbbb喷潮片| 国语自产精品视频在线看一大j8| 亚洲欧美成人在线| yellow中文字幕久久| 精品国产乱码久久久久酒店| 国产一区二区色| 中文字幕在线国产精品| 黑人精品xxx一区一二区| 欧美日韩中文字幕在线| 欧美日韩综合视频网址| 亚洲精品午夜精品| 久操成人在线视频| 在线视频免费一区二区| 欧美性视频网站| 国产精品高潮呻吟久久av黑人| 日韩精品中文字幕视频在线| 欧美区在线播放| 性视频1819p久久| 亚洲国产精品久久久久久| 久久久国产精品一区| 国产成人高清激情视频在线观看| 亚洲精品动漫久久久久| 成人两性免费视频| 55夜色66夜色国产精品视频| 亚洲人成网站免费播放| 日韩一区二区三区国产| 国产精品一区二区电影| 亚洲丁香久久久| 日韩在线免费视频| 精品无人国产偷自产在线| 欧美中文字幕第一页| 国产98色在线| 麻豆国产va免费精品高清在线| 在线观看精品国产视频| 国产精品久久久久久久av电影| 欧美精品少妇videofree| 欧美极品欧美精品欧美视频| 中文字幕日韩精品在线观看| 亚洲图片欧美午夜| 欧美成aaa人片在线观看蜜臀| 久久夜色精品国产亚洲aⅴ| 亚洲国产小视频| 中文字幕亚洲欧美日韩2019| 欧美老女人在线视频| 欧美激情中文网| 久久久久一本一区二区青青蜜月| 国产精品视频在线播放| 国产精品美女久久久久av超清| 精品日本高清在线播放| 亚洲高清一二三区| 久久久久久久久久av| 欧美野外猛男的大粗鳮| 91地址最新发布| 中文字幕日韩在线播放| 久久久久久久久久久久久久久久久久av| 欧洲精品久久久| 日韩欧美999| 亚洲综合色av| 91性高湖久久久久久久久_久久99| 狠狠操狠狠色综合网| 红桃视频成人在线观看| 国产一区二区成人| 精品调教chinesegay| 久久国产精品首页| 欧美一级黑人aaaaaaa做受| 久久久久一本一区二区青青蜜月| 78色国产精品| 中文字幕日韩精品在线观看| 中文字幕不卡av| 国产精品美女呻吟| 精品国偷自产在线视频99| 亚洲欧美日韩直播| 自拍偷拍亚洲在线| 国产精品视频大全| 久久久久久久久国产| 亚洲视频电影图片偷拍一区| 久久久久久国产精品美女| 亚洲第一网中文字幕| 国产精品国产自产拍高清av水多| 久久久久久国产精品美女| 亚洲精品一区av在线播放| 91精品视频观看| 亚洲综合在线播放| 欧美精品一区二区免费| 国产成人福利夜色影视| 日韩av在线免播放器| 欧美午夜女人视频在线| 日韩精品999| 亚洲毛茸茸少妇高潮呻吟| 影音先锋欧美在线资源| 久久露脸国产精品| 欧美在线视频一区二区| 黄色成人av网| 久久影视电视剧免费网站清宫辞电视| 色爱精品视频一区| 日韩a**中文字幕| 国产精品成人va在线观看| 理论片在线不卡免费观看| 韩国19禁主播vip福利视频| 亚洲成人免费网站| 亚洲跨种族黑人xxx| 亚洲成人免费在线视频| 亚洲永久免费观看| 欧美激情第三页| 日韩高清电影免费观看完整版| 亚洲欧美综合精品久久成人| 欧美日韩午夜激情| 国产精品白丝av嫩草影院| 欧美性xxxx极品高清hd直播| 91国产精品91| 国产成人综合久久| 国产福利精品视频| 欧美日韩国产中文字幕| 久久精品美女视频网站| 亚洲欧美精品伊人久久| 欧美大学生性色视频| 国产在线视频2019最新视频| 久久夜精品香蕉| 久久久久中文字幕2018| 国产综合在线看| 国产午夜精品一区理论片飘花| 久久精品国产欧美亚洲人人爽| 国产精品久久久久久五月尺| 97国产成人精品视频| 欧美激情一区二区三区在线视频观看| 欧美另类第一页| 午夜精品久久久久久久白皮肤|