2014年6月11日 星期三

Mask 遮罩延遲顯示的狀況

前一陣子碰到一問題!
先前寫過一個遮罩的功能,可以讓PG呼叫遮罩,然後進行AJAX處理

讓使用者等待畫面處理完成!

最近有人反應,他們使用後發現,部份的頁面會產生延遲顯示的狀況!!
也就是遮罩不會馬上顯示~

便開始追查問題

首先先用chrome來進行Timeline的錄製

發現當我按下儲存的時侯(click事件)

畫面就停住了,便產生了大量的GC javascript Heap高達 94MB

所以針對程式一看~

嗯,事出必有因,畫面的行為如下:

1、畫面上有近1000個checkbox
2、當按下送出的時侯會針對checkbox 進行取值,有選取的就加入陣例(透過Each的方式)

想了一下,這應該是因為進行了javascript的大量運算,所以遮罩完全跑不出來 UI的Thread就停了

所以便寫了一個測試程式:
1、產生一個簡單的For計算,j++
  var j = 0;
  for (var i = 0; i < 1000000000; i++) {//讓JS產生一個大量運算
   j++;
  }
 console.log(j);
2、透過Deferred 物件,保證執行完成
var dtd = $.Deferred(); // 新建deferred

3、透過setTimeout 讓畫面延遲5秒,直到動畫完成
 setTimeout(tasks, 5000); // 停頓5秒

這邊可能有人覺得奇怪,為何還要設定SetTimeout 5秒後才執行程式
我們已經使用了Deferred的物件了,應該可以保證事件執行完成
但是經過測試,我們確實是保證物件有執行了,但~因為我們後續馬上執行了一個大量運算
其實是會導致Browser偵測到一個JS佔用到太多CPU,而產生停止的訊息,所以導致動畫也無法完整執行完畢

失敗
               var dtd = $.Deferred(); // 新建deferred

                var show = function (dtd) {
                    var tasks = function () { //裡面請放置你的主程式!
                        funOpenLoadingMask(true);
                        dtd.resolve(); // deferred的狀態改變
                    };
                    tasks();
                    return dtd.promise();
                };

                $.when(show(dtd))
                .then(function () {
                    var j = 0;
                    for (var i = 0; i < 1000000000; i++) {//讓JS產生一個大量運算
                        j++;
                    }
                    console.log(j);
                }).done(funOpenLoadingMask(false))

成功
                 var show = function (dtd) {
                    funOpenLoadingMask(true);

                    var tasks = function () { //裡面請放置你的主程式!
                        var j = 0;
                        for (var i = 0; i < 1000000000; i++) {//讓JS產生一個大量運算
                            j++;
                        }
                        console.log(j);
                        dtd.resolve(); // deferred的狀態改變
                    };
              
                    setTimeout(tasks, 5000); // 停頓5秒
                    return dtd.promise();
                };
               
                $.when(show(dtd))
               .then(function () {
                    funOpenLoadingMask(false);
                });


附上檔案

沒有留言:

張貼留言