1. 程式人生 > >Ajax同步請求出現瀏覽器頁面假死,阻塞UI執行緒之解決方案

Ajax同步請求出現瀏覽器頁面假死,阻塞UI執行緒之解決方案

原始碼:function loadCheckBox(){
var busVedioPosition = '';
var defer = new jQuery.Deferred();
$.ajax({
url:rootPath + "/gis/getBusVedioPosition",
//async:false,
type:"POST",
success:function(result){
defer.resolve(result);
//alert(result.busVedioPosition);
//console.log(result.busVedioPosition);
if(result.success && result.busVedioPosition){
busVedioPosition = result.busVedioPosition;//array
//debugger;
var checkBoxHtml = '';
for(var i=0;i<busVedioPosition.length;i++){

var vehType = document.getElementById("vehTypeCar").value;
var checkBox = document.getElementById("mviewlCheckBox");
if(vehType==0&&busVedioPosition[i].vechType==0){


checkBoxHtml += "<div class=\"checkBoxCss\"><input type=\"checkbox\" onclick=\"checkboxChange(this);\" value="+busVedioPosition[i].passageWayId.substring(5)+">"+busVedioPosition[i].passageWayName+"</div>";
checkBox.innerHTML = checkBoxHtml;
}else if(vehType==1&&busVedioPosition[i].vechType==1){

checkBoxHtml += "<div class=\"checkBoxCss\"><input type=\"checkbox\" onclick=\"checkboxChange(this);\" value="+busVedioPosition[i].passageWayId.substring(5)+">"+busVedioPosition[i].passageWayName+"</div>";
checkBox.innerHTML = checkBoxHtml;


}
}
}
}
});
return defer;
//return defer.promise();


}

問題描述:從庫中拿出資料後根據var vehType = document.getElementById("vehTypeCar").value的值向jsp中新增innerHTML類容;
   前提是vehType 有值,而它的值來自於頁面中EL表示式接收穫取的,所有存在邏輯順序的問題;

                    如果上面程式碼中的async為false,也就是同步獲取的話,就會執行卡死在js(jQuery)中,搜尋一番說是js和頁面UI渲染互斥

---引用--- 

(原話:“在發起同步Ajax請求時設定的等待圖片在IE與Chrome瀏覽器不顯示,在firefox裡面正常,通過Chrome debug模式發現,它是會顯示的,由於後面的計算是JQuery同步操作,需要過長時間計算,導致介面UI卡死(來不及展示)。


瀏覽器的渲染(UI)執行緒和js執行緒是互斥的,在執行js耗時操作時,頁面渲染會被阻塞掉。當我們執行非同步ajax的時候沒有問題,但當設定為同步請求 時,其他的動作(ajax函式後面的程式碼,還有渲染執行緒)都會停止下來。即使DOM操作語句是在發起請求的前一句,這個同步請求也會“迅速”將UI線 程阻塞,不給它執行的時間。這就是程式碼失效的原因。jQuery在1.5版本之後,引入了Deferred物件,提供的很方便的廣義非同步機制。
deferred物件就是jQuery的回撥函式解決方案,deferred物件的含義就是"延遲"到未來某個點再執行。
$.ajax()操作完成後,如果使用的是低於1.5.0版本的jQuery,返回的是XHR物件,你沒法進行鏈式操作;如果高於1.5.0版本,返回的是deferred物件,可以進行鏈式操作。
”出處:http://blog.csdn.net/u012654922/article/details/50113315)

最後:通過對最初程式碼(下方)

function loadCheckBox(){
var busVedioPosition = '';

//--------------------①
$.ajax({
url:rootPath + "/gis/getBusVedioPosition",
async:false,//--------------------②
type:"POST",
success:function(result){

//--------------------③
if(result.success && result.busVedioPosition){
busVedioPosition = result.busVedioPosition;//array
var checkBoxHtml = '';
for(var i=0;i<busVedioPosition.length;i++){
var vehType = document.getElementById("vehTypeCar").value;
var checkBox = document.getElementById("mviewlCheckBox");
if(vehType==0&&busVedioPosition[i].vechType==0){
checkBoxHtml += "<div class=\"checkBoxCss\"><input type=\"checkbox\" onclick=\"checkboxChange(this);\" value="+busVedioPosition[i].passageWayId.substring(5)+">"+busVedioPosition[i].passageWayName+"</div>";
checkBox.innerHTML = checkBoxHtml;
}else if(vehType==1&&busVedioPosition[i].vechType==1){
checkBoxHtml += "<div class=\"checkBoxCss\"><input type=\"checkbox\" onclick=\"checkboxChange(this);\" value="+busVedioPosition[i].passageWayId.substring(5)+">"+busVedioPosition[i].passageWayName+"</div>";
checkBox.innerHTML = checkBoxHtml;
}
}
}
}
});
//--------------------
}

解決辦法:

① 加上      var defer = new jQuery.Deferred();

② 註釋掉  async(或者刪除)

③ 加上     defer.resolve(result);

④ 加上     return defer;