麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > JavaScript > 正文

Jquery ajax 同步阻塞引起的UI線程阻塞問題

2019-11-20 11:15:06
字體:
來源:轉載
供稿:網友

最近做一個項目,遇到了一個問題同步ajax引起的ui線程阻塞問題,下面把我的問題解決過程分享給大家。

事情起因是這樣的,因為頁面上有多個相似的異步請求動作,本著提高代碼可重用性的原則,我封裝了一個名為getData的函數,它接收不同參數,只負責獲取數據,然后把數據return。基本的邏輯剝離出來是這樣的:

function getData1(){    var result;    $.ajax({      url : "p.php",      async : false,      success: function(data){        result = data;      }    });  return result;} 

這里的ajax不能用異步的,否則函數返回時,result還未賦值,會出錯。所以我加了async:false。看起來好像沒什么問題。我調用這個函數可以正常的得到數據。

$(".btn1").click(function(){    var data = getData1();    alert(data);});

接下來,要加另外一個功能,由于ajax請求有一定的耗時,所以我需要在發出請求前頁面有個loading效果,即顯示一張“正在加載”的gif圖片,想必大家也都見過。所以我的處理函數就變成了這樣:

$(".btn1").click(function(){    $(".loadingicon").show();    var data = getData1();    $(".loadingicon").hide();    alert(data);});

請求之前顯示loading圖片,請求完成后把它隱藏。看起來也沒什么問題。為了看清效果,我的p.php代碼sleep了3秒,如下:

<?phpsleep(3);echo ("aaaaaa");?>

但是我運行的時候問題出現了,我點擊按鈕并未像預想的那樣出現這個loading圖片,頁面什么反應也沒有。排除良久找到了原因,就在async:false這里。

瀏覽器的渲染(UI)線程和js線程是互斥的,在執行js耗時操作時,頁面渲染會被阻塞掉。當我們執行異步ajax的時候沒有問題,但當設置為同步請求時,其他的動作(ajax函數后面的代碼,還有渲染線程)都會停止下來。即使我的DOM操作語句是在發起請求的前一句,這個同步請求也會“迅速”將UI線程阻塞,不給它執行的時間。這就是代碼失效的原因。

setTimeout解決阻塞問題

  既然明白了問題在哪里,我們就來針對性想辦法。為了不讓同步ajax請求阻塞線程,我想到了setTimeout,把請求的代碼放到sestTimeout中,讓瀏覽器重啟一個線程來操作,不就解決問題了嗎?于是乎,我的代碼就變成了這樣:

$(".btn2").click(function(){    $(".loadingicon").show();    setTimeout(function(){      $.ajax({        url : "p.php",        async : false,        success: function(data){          $(".loadingicon").hide();          alert(data);        }      });    }, 0);}); 

setTimeout的第二個參數設為0,瀏覽器會在一個已設的最小時間后執行。不管三七二十一先運行起來看看。

  結果loading圖片顯示出來了,但是!!!圖片怎么不動呢,我明明是一張動態gif圖。這個時候我很快就想到了,雖然同步請求延遲執行了,但是它執行期間還是會把UI線程給阻塞。這個阻塞相當牛逼,連gif圖片都不動了,看起來像一張靜態圖片一樣。

  結論很明顯,setTimeout治標不治本,相當于把同步請求“稍稍”異步了一下,接下來還是會進入同步的噩夢,阻塞線程。方案失敗。

是時候用Deferred了

  jQuery在1.5版本之后,引入了Deferred對象,提供的很方便的廣義異步機制。詳情可參看阮一峰老師的這篇文章http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

  于是我用Deferred對象改寫了代碼,如下:

function getData3(){    var defer = $.Deferred();    $.ajax({      url : "p.php",      //async : false,      success: function(data){        defer.resolve(data)      }    });    return defer.promise();}  $(".btn3").click(function(){    $(".loadingicon").show();    $.when(getData3()).done(function(data){      $(".loadingicon").hide();      alert(data);    });});

可以看到我在ajax請求中去掉了async:false,也就是說,這個請求又是異步的了。另外請注意success函數中的這一 句:defer.resolve(data),Deferred對象的resolve方法可傳入一個參數,任意類型。這個參數可以在done方法中拿到, 所以我們異步請求來的數據就可以以這樣的方式來返回了。

  至此,問題得到了解決。Deferred對象如此強大且方便,我們可以好好利用它。

  我的全部測試代碼如下,有意的同學可以拿去測一下:

<button class="btn1">async:false</button><button class="btn2">setTimeout</button><button class="btn3">deferred</button><img class="loadingicon" style="position:fixed;left:50%;top:50%;margin-left:-16px;margin-top:-16px;display:none;" src=http://www.update8.com/Web/Jquery/"loading2.gif" alt="正在加載" /><script>  function getData1(){    var result;    $.ajax({      url : "p.php",      async : false,      success: function(data){        result = data;      }    });    return result;  }  $(".btn1").click(function(){    $(".loadingicon").show();    var data = getData1();    $(".loadingicon").hide();    alert(data);  });  $(".btn2").click(function(){    $(".loadingicon").show();    setTimeout(function(){      $.ajax({        url : "p.php",        async : false,        success: function(data){          $(".loadingicon").hide();          alert(data);        }      });    }, 0);  });  function getData3(){    var defer = $.Deferred();    $.ajax({      url : "p.php",      //async : false,      success: function(data){        defer.resolve(data)      }    });    return defer.promise();  }    $(".btn3").click(function(){    $(".loadingicon").show();    $.when(getData3()).done(function(data){      $(".loadingicon").hide();      alert(data);    });  });</script>

ps:$.ajax的參數描述

參數 描述

url 必需。規定把請求發送到哪個 URL。
data 可選。映射或字符串值。規定連同請求發送到服務器的數據。
success(data, textStatus, jqXHR) 可選。請求成功時執行的回調函數。
dataType 
可選。規定預期的服務器響應的數據類型。
默認執行智能判斷(xml、json、script 或 html)。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 欧美伦交| 一级黄色片武则天 | 少妇淫片免费一级毛片 | 免费a级黄色片 | 欧美黑人伦理 | japanese xxxxhd | 午夜精品久久久久久久99热浪潮 | 国产chinesehd精品91 | 欧美日韩一区,二区,三区,久久精品 | 青青草免费观看完整版高清 | 亚洲精品一区二区三区免 | 国产女做a爱免费视频 | 福利在线小视频 | 色柚视频网站ww色 | 久久国产精品久久久久久电车 | 素人视频免费观看 | 国产免费传媒av片在线 | h视频免费在线观看 | 精品国产一区二区亚洲人成毛片 | 黄色网址在线播放 | 毛片免费视频在线观看 | 久久精品观看 | 亚洲第一视频在线 | 男人天堂免费 | 精品一区二区三区免费毛片爱 | 美女在线视频一区二区 | 中文字幕 亚洲一区 | 免看黄大片aa| 麻豆视频在线观看免费网站 | 欧美激情猛片xxxⅹ大3 | 深夜视频福利 | 国产一级二级在线播放 | 男女一边摸一边做羞羞视频免费 | 亚洲一区 国产精品 | 久久久久久麻豆 | 在线影院av| 99最新网址 | 国产色91| www.99热精品| 精品亚洲视频在线 | 国产毛片在线 |