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

          給你的元素加一把鎖--Prototype.js

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

          ?  在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一下了。

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

          ?


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 乌鲁木齐县| 吴旗县| 福海县| 汤原县| 会理县| 垫江县| 巴塘县| 土默特右旗| 双柏县| 鄱阳县| 钟山县| 屏东市| 和平区| 舟山市| 荥阳市| 安仁县| 恩平市| 遵义县| 饶平县| 呈贡县| 工布江达县| 洛隆县| 双流县| 越西县| 兴山县| 巴彦县| 和龙市| 澎湖县| 威远县| 浦江县| 邯郸县| 平顶山市| 五台县| 扎囊县| 山东省| 小金县| 衡水市| 闵行区| 沐川县| 自贡市| 塘沽区|