posts - 3, comments - 1, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          2006年9月14日

          ?  在Ajax應用中,我們常常要頻繁更改某一元素的值。例如有一ID為"pageBody"的元素,我們想把所有文章內容都在這里顯示,做到局部刷新的Ajax應用。但如果因為網速較慢,使得此元素在接收信息時就被用戶執行其它行為,而改變此元素的內容了,而之前的接收信息的線程還在進行著,當此線程完成了,又把pageBody的值改了一下,此時用戶會覺得不知所措,怎么這塊東西閃來閃去的?嚴重者,會因為子元素的消失而出現JS錯誤的現象。
            為了解決此問題,有兩個方法:第一、在執行線程(假設執行一次取值為一個線程)的時候,建立一個滿屏的DIV,使得用戶無法執行其它行為;第二、制作一把鎖,把此元素鎖起來,當其它線程想改變它的值時先查檢此元素是否上鎖。
            第一種方法使得用戶進入了等待狀態,雖然頁面沒有刷新,但與沒有使用Ajax的頁面沒什么分別,所以在非不得已的情況下都不要使用此方法。
            下面我說說第二種方法--制作元素鎖。
            其實要實現這個鎖,原理很簡單,與java中的線程鎖有點類似,可惜偶對java的線程鎖理解不深入,所以在javaScript中此鎖與java的線程鎖應該又會有很大的不同,甚至完全不是一個回事。
            首先,我們需要一個Object,?

          var ?_key = {key:key,value: true };

          其中key為此對象的標識,value是否為真就等于是否為鎖定。
          在java中,每一個Object對象都可以用作鎖,但javaScript中不同,而且通過

          1??while(true){
          2???if(condition)?break;
          3??}

          的方法根本行不通,因為這個while(true)會讓瀏覽器僵死,Firefox會提示是否繼續執行腳本,IE可能會說腳本有誤,殺毒軟件可能說這是病毒!
            為了能統領全局,更靈活的掌控它,我們把鎖都放到一個數組中:

          1??var?_mainlock=[];

          同時,為了方便應用,我使用了Prototype.js,以擴展Array的方法,主要用這三個方法:
          1、detect(iterator):集合中每個元素調用一次Iterator,返回第一個使Iterator返回True的元素,如果最終都沒有為true的調用,那么返回null。
          ?2、reject(iterator):返回所有等于false的元素。
          ?3、each(iterator):把每個element做為第一個參數,element的index作為第一個參數調用iterator函數。
          ?有了它們,我們可以創建一個Push來給 _mainlock加入唯一key的鎖,類似HashMap原理:

          ? var ?_Push = function (Obj) {
          ??
          var ?unIns = _mainlock.reject( function (d) { return ?d.key == Obj.key;} );
          ??_mainlock
          = unIns;
          ??_mainlock.push(Obj);
          ?}


          只要執行_Push(_key)就可以把對象放入這個偽HashMap中去。如果已有相同的key的對象,則會覆蓋它,沒有就直接放入。

          var ?get = function (key) {
          ??
          return ?_mainlock.detect( function (d) { return ?d.key == key;} );
          ?}
          ;


          ?通過這個方法,就可以取得相應Key的鎖了。
          ?因為JavaScript對DOM的操作有著很多未知性,不可能總是通過我們預先定義的變量來滿足要求,如一個列表,可能是有一行,也可能上千行,每一行的ID又是獨立的,所以我們只能用另外的方法來預見之此行為,那就是通過應用HashMap的特性,以string為標識的唯一Key來統領所有將可能發生的事件。因此,再寫一個方法:

          ? var ?Lock = function (key) {
          ??
          var ?_key = {key:key,value: true } ;
          ??_Push(_key);
          ??
          return ? true ;
          ?}
          ;


          這樣,只要有一個string類型的key,就可以建立一個鎖對象了。以后,對鎖的建立和獲取,都可以通過上面三個方法來實現,只要一個string作為Key來操作鎖,而無需知道鎖的內部是如何構造。
          接下來,我們要實現isWait(),sleep(),awake()和awakeAll()方法,以完善這個鎖:

          ? var ?isWait = function (key) { // 返回真表示鎖,否則表示非鎖
          ?? var ?ins = GDnews.get(key);
          ??
          if (ins)? return ?ins.value;
          ??
          return ? false ;
          ?}
          ;
          ?
          var ?sleep = function (key,time) { // 給鎖上鎖指定秒數,若干秒后自動解鎖
          ??GDnews.Lock(key);
          ??window.setTimeout(
          function () {GDnews.awake(key)} ,time);
          ?}
          ;
          ?
          var ?awake = function (key) { // 強行開鎖
          ?? var ?_key = {key:key,value: false } ;
          ??GDnews._Push(_key);
          ??
          return ? false ;
          ?}
          ;
          ?
          var ?awakeAll = function () { // 強行打開所有鎖
          ?? if ( ! GDnews._mainlock)? return ? " all " ;
          ??
          var ?newList = [];
          ??GDnews._mainlock.each(
          function (d,index) {
          ???d.value
          = false ;
          ???newList.push(d);
          ??}
          );
          ??GDnews._mainlock
          = newList;
          ??
          return ? false ;
          ?}
          ;
          ?



          ?以后,當你使用Prototype.js的快捷鍵$()時,就可以看看目標是否為isWait,否的話就可以Lock或者sleep一下了。

          ?以上就是全文內容,請各位指點。

          ?

          posted @ 2006-09-14 18:26 govo 閱讀(369) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 隆尧县| 化州市| 弋阳县| 肥西县| 彩票| 汉川市| 邢台县| 潍坊市| 石河子市| 林芝县| 济南市| 桐梓县| 得荣县| 葫芦岛市| 新民市| 综艺| 彩票| 宁陕县| 陆河县| 繁昌县| 将乐县| 手游| 旺苍县| 静安区| 鄂温| 仁怀市| 望奎县| 丹巴县| 涟水县| 皮山县| 安陆市| 拉孜县| 鹤岗市| 水城县| 三明市| 凤冈县| 华阴市| 鄂尔多斯市| 永康市| 湖州市| 内黄县|