js阻塞ui進程涉及的知識點整理


項目進行中遇到了同步ajax阻塞ui線程阻塞的問題,原因是執行兩個同步ajax請求為一次完整的方法,因業務需求需要循環執行這個方法,檢查后台返回的數據正確,但是由於ajax請求時間過長,考慮增加遮罩層與loading圖標,

這時遇到該問題,loading圖標 .后面的出圖也是所有方法執行后只出一個圖

代碼類似於這樣:

$(function(){
    for(var key in data){//循環執行
       $('#mask').css('display','block');//遮罩層
       doAjax();        
       $('#mask').css('display','none');//去除遮罩層 
    }
   
});

var doAjax = {
   aAjax:function(){//第一個ajax請求
      ajax({
          async:false
          url:url,
          success:function(){
              doAjax.bAjax();
          }
      });
    };
   bAjax : function(){//第二個ajax請求
        ajax({
            async:false
            url:url,
            success:function(){
               doAjax.doHightCharts();
           }
        });
     };
   doHighCharts:function(){
         //出圖
    }
}    
    

此時為每一個過程考慮兩次js阻礙ui線程的加載,第一次添加遮罩層時,第二次為加載highcharts出圖時.

考慮兩次的原因均因為async:false的原因.由於瀏覽器的渲染(UI)與與js線程是互斥的,在執行js耗時操作時,頁面渲染會被阻塞掉。當我們執行異步ajax的時候沒有問題,但當設置為同步請求時,其他的動作(ajax函數后面的代碼,還有渲染線程)都會停止下來。即使我的DOM操作語句是在發起請求的前一句($('#mask').css('display','block');//遮罩層),這個同步請求也會“迅速”將UI線程阻塞,不給它執行的時間。這就是代碼失效的原因。

在探究這個問題時,了解到更多的知識:(由於項目工期緊,沒能使用各種方法實現)

jQuery的deferred對象

項目中的這個難題使用最簡單易懂的方式:

setTimeout解決阻塞問題:

var flag = {
   num:0
}
$(function(){
    $('#mask').css('display','block');//遮罩層
   setTimeout{//首先執行一次
       doAjax(),0        
    }
 
});

var doAjax = {
   aAjax:function(){//第一個ajax請求
      ajax({
          async:true,//可以異步
          url:url,
          success:function(){
              doAjax.bAjax();
          }
      });
    };
   bAjax : function(){//第二個ajax請求
        ajax({
            async:true,//可以異步
            url:url,
            success:function(){
                  flag.num++;//此時執行避免異步
                    if (flag.num < data.length) {
                        setTimeout(doAjax.aAjax(), 100);
                    }
                   doAjax.doHightCharts();
                   if(flag.num==data.length){
                      $('#mask').css('display','none');//去除遮罩層
                    }
           }
        });
     };
   doHighCharts:function(){
         //出圖
    }
}    
                                                                

 

此時簡單來說,setTimeout將方法排列的js執行隊列的最后(哪怕設置第二個參數為0),所以說使用setTimeout是為了確保UI刷新線程不被阻塞.

理解此過程可以根據:

js單線程淺談

js線程

在這里進行簡單的總結:

1.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM