2014/01/21

[心得] UltraWebGrid 全選時的效能問題

公司的 Grid 設定每一個 Row 前面會有一個 Checkbox,checkbox 按下去時會去觸發一個 onclick 事件,去檢查所選中的 Rows 的值來判斷畫面上的某些功能作用 or 不作用

另外產品也另外做了一個控件,負責處理全選/全不選等等,該控件的功能為選取(取消選取)全部的checkbox,並且用 fireEvent (for IE) 觸發每 Row 上 checkbox 的 onclick 事件去檢查畫面上的功能於目前的狀態是否適用

素晴らしいです ~~!


but!

在目前的這個案子中,這個功能不知道被怎麼改的,按下全選之後竟然要拖到超過一分鐘才能把所有的資料給選起來,甚至是偶爾在某些功能區一筆一筆勾選時就會選到要當掉去

於是...  讓他變成跟產品差不多快的任務就出現了 XD

仔細看一下 code 會發現,在觸發 checkbox 的 onclick 時會執行這個 function:


function SelectRow(aaaaa, bbbbb, ccccc, ddddd, eeeee) {
 //... 前略 ...
    if (HidValue > 1 && document.getElementById(strPreText + "hidType").value == "1") {
        if (sc == "Y" && scur1 == "Y") {
           //...  
        }
        else if (FnChk(strCODE) == false) 
        {
           //...
        }
        else if (scur1 == "Y" && sc == "N" && end1 == "Y" && end == "N" 
                  && strHdlTrue == "Y" && strHdlFalse == "N" && FnChk(strCODE)) {
            //...
        }
        else if (scur1 == "N" && sc == "Y" && end1 == "Y" && end == "N" 
                  && strHdlTrue == "Y" && strHdlFalse == "N" && FnChk(strCODE)) {
            //...
        }
        else if (scur1 == "Y" && sc == "N" && end1 == "N" && end == "Y" 
                  && strHdlTrue == "Y" && strHdlFalse == "N" && FnChk(strCODE)) {
            //...
        }
        else if (scur1 == "N" && sc == "Y" && end1 == "N" && end == "Y" 
                  && strHdlTrue == "Y" && strHdlFalse == "N" && FnChk(strCODE)) {
           //...
        }
    }
 //... 後略 ...
}

先不管這一堆 if else 的code 是不是很髒 XD

在 SelectRow 這個 funciton 裡面有好幾個地方 call 了 FnChk 這個 Funciton 並傳入了 strCODE 的值

那再來看看這個 FnChk 做了啥事:

function FnChk(strCODE) {
    var xmlHttp = GetXmlHttpRequest();
    strpass = "XXXXXXXXX.ASPX?vstrCODE=" + escape(strCODE) + "&Flag=3";
    xmlHttp.open("POST", strpass, false);
    xmlHttp.send("");
    var result = xmlHttp.responseText;
    if (result == "NO") 
        return false;
    else
        return true;
}

他做的事情是
  1. 拿到一個變數
  2. 發起一個 XmlHttpRequest
  3. 取回 XmlHttpRequest 回傳的字串
  4. 檢查當回傳字串為"NO"時 return false;
用 XmlHttpRequest 在資料勾選時才回去檢查目前這筆資料的狀態是有其用處在,避免使用者在同一個畫面下停留太久 Grid 的資料已經不是最新的狀態下還針對過期資料做處理

但是....

在一次 SelectRow 執行的途中針對同筆資料重複的去發起 XmlHttpRequest 判斷狀態的作法通常取回的都會是同一個狀態,上面的 code 就花了 5 個連線只為了要一個 Boolean (實際上的code更多...)

而這個問題也間接導致了全選時效率低到哭的問題

假設有 200 筆資料被全選將會對 server 發起 1000 次連線,同時有 10 個人在這個功能上對200筆資料做全選就會發起 10000 次連線

如果 Server 爛一點就會被當做駭客攻擊了 XD

比較健康的作法應該是在 function 的一開始就把這個 Boolean 給拿回來

var chk= FnChk(strCODE);

然後針對這個 chk 去判斷就好了

或者是少用的功能等到那個功能被點下去時再發起 XmlHttpRequest 去檢查資料的正確性

又或者是如果這個資料的異動幾乎不可能存在 (譬如資料的 CreateDate or CreateUser),那更可以在 Grid 撈資料的同時就先撈到 Row 裡面用 Hidden 的方式記住

把 XmlHttpRequest 從這個 function 拔掉之後,Grid 就重振雄風了~  全選超快的科科

沒有留言:

張貼留言